Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions apps/frontend/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
'use client';

import { useState } from 'react';
import StatusTabs from '@/component/dashboard/StatusTabs';
import EscrowList from '@/component/dashboard/EscrowList';
import EscrowFilters from '@/component/dashboard/EscrowFilters';
import { useEscrows } from '../../hooks/useEscrows';
import { IEscrow } from '@/types/escrow';

export default function DashboardPage() {
const [activeTab, setActiveTab] = useState<'all' | 'active' | 'pending' | 'completed' | 'disputed'>('all');
const [searchQuery, setSearchQuery] = useState('');
const [sortBy, setSortBy] = useState<'date' | 'amount' | 'deadline'>('date');
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');

const {
data: escrowsData,
isLoading,
isError,
hasNextPage,
fetchNextPage,
isFetchingNextPage
} = useEscrows({
status: activeTab,
search: searchQuery,
sortBy,
sortOrder
});

// Flatten the paginated data
const flatEscrows = escrowsData?.pages.flatMap((page: any) => page.escrows) || [];

// Handle tab changes
const handleTabChange = (tab: 'all' | 'active' | 'pending' | 'completed' | 'disputed') => {
setActiveTab(tab);
};

// Handle search
const handleSearchChange = (query: string) => {
setSearchQuery(query);
};

// Handle sort change
const handleSortChange = (field: 'date' | 'amount' | 'deadline', order: 'asc' | 'desc') => {
setSortBy(field);
setSortOrder(order);
};

return (
<div className="min-h-screen bg-gray-50 py-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-10">
<h1 className="text-3xl font-extrabold text-gray-900 sm:text-4xl">
Escrow Dashboard
</h1>
<p className="mt-4 text-lg text-gray-500">
Manage all your escrow agreements in one place
</p>
</div>

<div className="bg-white rounded-lg shadow-md p-6">
<StatusTabs activeTab={activeTab} onTabChange={handleTabChange} />

<EscrowFilters
searchQuery={searchQuery}
onSearchChange={handleSearchChange}
sortBy={sortBy}
sortOrder={sortOrder}
onSortChange={handleSortChange}
/>

<EscrowList
escrows={flatEscrows}
isLoading={isLoading}
isError={isError}
activeTab={activeTab}
hasNextPage={hasNextPage}
fetchNextPage={fetchNextPage}
isFetchingNextPage={isFetchingNextPage}
/>
</div>
</div>
</div>
);
}
15 changes: 11 additions & 4 deletions apps/frontend/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import Providers from "@/component/Providers";
import Navbar from "@/component/layout/Navbar";

const geistSans = Geist({
variable: "--font-geist-sans",
Expand All @@ -13,8 +15,8 @@ const geistMono = Geist_Mono({
});

export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: "Vaultix - Secure Escrow Platform",
description: "Decentralized escrow platform built on Stellar blockchain",
};

export default function RootLayout({
Expand All @@ -27,8 +29,13 @@ export default function RootLayout({
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
<Providers>
<Navbar />
<main className="pt-16">
{children}
</main>
</Providers>
</body>
</html>
);
}
}
141 changes: 63 additions & 78 deletions apps/frontend/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,105 +1,90 @@

import Image from "next/image";

export default function Home() {
return (
<div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={180}
height={38}
priority
/>
<ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left">
<li className="mb-2 tracking-[-.01em]">
Get started by editing{" "}
<code className="bg-black/[.05] dark:bg-white/[.06] font-mono font-semibold px-1 py-0.5 rounded">
app/page.tsx
</code>
.
</li>
<li className="tracking-[-.01em]">
Save and see your changes instantly.
</li>
</ol>
<div className="flex items-center">
<div className="h-16 w-16 relative mr-4">
<div className="absolute inset-0 bg-gradient-to-r from-purple-600 to-blue-500 rounded-lg transform rotate-45"></div>
<div className="absolute inset-1 bg-black rounded-lg transform flex items-center justify-center">
<span className="text-transparent bg-clip-text bg-gradient-to-r from-purple-400 to-blue-400 font-bold text-2xl">
V
</span>
</div>
</div>
<h1 className="text-4xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-purple-600 via-blue-500 to-teal-400">
Vaultix
</h1>
</div>

<div className="text-center max-w-2xl">
<h2 className="text-2xl font-bold text-gray-900 mb-4">
Secure Decentralized Escrow Platform
</h2>
<p className="text-lg text-gray-600 mb-8">
Protect your transactions with smart escrow agreements powered by Stellar blockchain technology.
</p>

<div className="flex flex-col sm:flex-row gap-4 justify-center">
<a
href="/dashboard"
className="rounded-full bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700 text-white font-medium text-lg px-8 py-3 transition-all duration-200 ease-in-out transform hover:scale-105 shadow-lg"
>
Access Dashboard
</a>
<a
href="/escrow/create"
className="rounded-full border-2 border-gray-300 hover:border-gray-400 text-gray-700 hover:text-gray-900 font-medium text-lg px-8 py-3 transition-all duration-200 ease-in-out transform hover:scale-105"
>
Create Escrow
</a>
</div>
</div>

<div className="flex gap-4 items-center flex-col sm:flex-row">
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Read our docs
</a>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 mt-12 max-w-4xl">
<div className="bg-white p-6 rounded-xl shadow-md border border-gray-100">
<div className="text-blue-600 text-3xl mb-4">🔒</div>
<h3 className="text-xl font-semibold text-gray-900 mb-2">Secure Transactions</h3>
<p className="text-gray-600">Smart contracts ensure funds are only released when conditions are met</p>
</div>

<div className="bg-white p-6 rounded-xl shadow-md border border-gray-100">
<div className="text-purple-600 text-3xl mb-4">⚡</div>
<h3 className="text-xl font-semibold text-gray-900 mb-2">Fast Settlement</h3>
<p className="text-gray-600">Blockchain-powered transactions settle in seconds, not days</p>
</div>

<div className="bg-white p-6 rounded-xl shadow-md border border-gray-100">
<div className="text-teal-600 text-3xl mb-4">🌐</div>
<h3 className="text-xl font-semibold text-gray-900 mb-2">Global Access</h3>
<p className="text-gray-600">Access your escrow agreements from anywhere in the world</p>
</div>
</div>
</main>
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">

<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
href="/dashboard"
>
<Image
aria-hidden
src="/file.svg"
alt="File icon"
width={16}
height={16}
/>
Learn
Dashboard
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
href="/escrow/create"
>
<Image
aria-hidden
src="/window.svg"
alt="Window icon"
width={16}
height={16}
/>
Examples
Create Escrow
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
href="https://github.com/Vaultix"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/globe.svg"
alt="Globe icon"
width={16}
height={16}
/>
Go to nextjs.org →
GitHub
</a>
</footer>
</div>
);
}
}
21 changes: 21 additions & 0 deletions apps/frontend/component/Providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use client';

import React, { useState } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

export default function Providers({ children }: { children: React.ReactNode }) {
const [queryClient] = useState(() => new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000, // 1 minute
retry: 1,
},
},
}));

return (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
}
Loading