diff --git a/app/analytics/freelancer/page.tsx b/app/analytics/freelancer/page.tsx deleted file mode 100644 index 33a6379..0000000 --- a/app/analytics/freelancer/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -'use client'; - -import FreelancerAnalyticsDashboard from '@/components/analytics/FreelancerAnalyticsDashboard'; - -export default function FreelancerAnalyticsPage() { - return ; -} diff --git a/app/analytics/leaderboard/page.tsx b/app/analytics/leaderboard/page.tsx deleted file mode 100644 index 15da1e0..0000000 --- a/app/analytics/leaderboard/page.tsx +++ /dev/null @@ -1,100 +0,0 @@ -'use client'; - -import { useEffect, useState } from 'react'; -import { useWallet } from '@/context/WalletContext'; - -type LeaderboardItem = { - address: string; - metric1?: number; - metric2?: number; -}; - -export default function LeaderboardPage() { - const [activeTab, setActiveTab] = useState<'lp' | 'freelancer'>('lp'); - const [period, setPeriod] = useState('all'); - const [data, setData] = useState([]); - const [loading, setLoading] = useState(false); - - const { address } = useWallet(); - - useEffect(() => { - const fetchData = async () => { - setLoading(true); - - try { - const res = await fetch(`/api/leaderboard?type=${activeTab}&period=${period}`); - const result = await res.json(); - setData(result); - } catch (err) { - console.error(err); - } - - setLoading(false); - }; - - fetchData(); - }, [activeTab, period]); - - const truncate = (addr: string) => `${addr.slice(0, 6)}...${addr.slice(-4)}`; - - const isUser = (addr: string) => addr.toLowerCase() === address?.toLowerCase(); - - return ( -
-

Leaderboard

- - {/* Tabs */} -
- - - -
- - {/* Filter */} - - - {/* Table */} -
- {loading ? ( -

Loading...

- ) : ( - - - - - - - - - - - - {data.slice(0, 20).map((row, i) => ( - - - - - - - ))} - -
RankAddressMetric 1Metric 2
{i + 1}{truncate(row.address)}{row.metric1 ?? '-'}{row.metric2 ?? '-'}
- )} -
-
- ); -} diff --git a/docs/architecture.md b/docs/architecture.md index d44c133..a4d738b 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -56,14 +56,14 @@ graph TD ## Route Surface -The primary route tree lives in `app/`. A small legacy `src/app/` tree still exists for older route experiments/tests and should be treated carefully when moving code. +The primary route tree lives in `app/`. For a complete overview of canonical routes, purposes, primary consumers, and active redirects, refer to the [Route Map](route-map.md). + +A small legacy `src/app/` tree still exists for older route experiments/tests and should be treated carefully when moving code. ``` app/ ├── admin/ # Admin health and protocol configuration -├── analytics/ # Protocol analytics -│ ├── freelancer/ # Freelancer cash-flow analytics -│ └── leaderboard/ # Analytics leaderboard view +├── analytics/ # Freelancer-specific cash-flow analytics (FreelancerAnalyticsDashboard) ├── api/ │ ├── auth/ # SEP-10 challenge and verify helpers │ ├── feedback/ # GitHub-backed feedback submission @@ -157,7 +157,7 @@ Contributor references for these server integrations live in [docs/supabase-setu - `ToastContext` wraps toast behavior while `AppToaster` renders the Sonner host. - `KeyboardShortcutsContext` manages keyboard shortcut state and global keydown listeners. - Page routes should compose feature components and hooks; reusable components should stay under `src/components/`. -- Stellar SDK and RPC details should stay in `src/utils/soroban.ts`, `src/lib/`, or focused hooks rather than being called directly from presentational components. +- Stellar SDK and RPC details should stay in `src/utils/soroban.ts`, `src/lib/`, or focused hooks rather than being called directly from presentational components. Integration status of live vs. stubbed contract details are tracked in [docs/contract-integration-status.md](contract-integration-status.md). ### Context vs Hooks Boundary diff --git a/docs/contract-integration-status.md b/docs/contract-integration-status.md new file mode 100644 index 0000000..a329a30 --- /dev/null +++ b/docs/contract-integration-status.md @@ -0,0 +1,52 @@ +# Smart Contract Integration Status + +This document tracks the integration status of Soroban smart contracts within the ILN Frontend codebase. It serves as a visibility guide for contributors and maintainers to know which features are fully backed by live on-chain contracts versus those that are currently stubbed or mock-implemented. + +## Integration Status Summary + +| Module | Sub-feature / Function | Status | Implementation File | Notes / Tracking Issue Link | +| :--- | :--- | :--- | :--- | :--- | +| **Invoices** | `submitInvoice` | **Real** | `src/utils/soroban.ts` | Fully integrated with deployed Soroban invoice contract. | +| **Invoices** | `fundInvoice` | **Real** | `src/utils/soroban.ts` | Fully integrated. | +| **Invoices** | `markPaid` | **Real** | `src/utils/soroban.ts` | Fully integrated. | +| **Invoices** | `appealDefault` | **Real** | `src/utils/soroban.ts` | Fully integrated. | +| **Invoices** | `disputeInvoice` | **Real** | `src/utils/soroban.ts` | Fully integrated. | +| **Invoices** | `claimDefault` | **Real** | `src/utils/soroban.ts` | Fully integrated. | +| **Invoices** | `cancelInvoice` | **Real** | `src/utils/soroban.ts` | Fully integrated. | +| **Invoices** | `updateLPWhitelist` | **Stubbed** | `src/utils/soroban.ts` | Throws error. Placeholder for upcoming whitelist manager contract. | +| **Reputation** | `getReputation` | **Real** | `src/utils/soroban.ts` | Fully integrated. | +| **Reputation** | `getPayerScore` | **Real** | `src/utils/soroban.ts` | Fully integrated. | +| **Governance** | `getProposals` | **Stubbed** | `src/utils/governance.ts` | Mocks return value; needs integration with deployed governance contract. | +| **Governance** | `castVote` | **Stubbed** | `src/utils/governance.ts` | Mock transaction; needs governance contract deployment. | +| **Governance** | `delegateVotingPower` | **Stubbed** | `src/utils/governance.ts` | Mock transaction; needs governance contract deployment. | +| **Governance** | `createProposal` | **Stubbed** | `src/utils/governance.ts` | Mock transaction; needs governance contract deployment. | +| **Governance** | `getGovTokenBalance` | **Stubbed** | `src/utils/governance.ts` | Mocks return balance; needs token contract integration. | +| **Governance** | `getQuorumThreshold` | **Stubbed** | `src/utils/governance.ts` | Mocks read-only call; needs governance contract deployment. | +| **Governance** | `getProposalHistory` | **Stubbed** | `src/utils/governance.ts` | Mocks timeline; needs Stellar SDK/Horizon lookup. | + +## Details of Stubbed Code & TODO Markers + +### 1. LP Whitelist Manager Stub +Located in `src/utils/soroban.ts` (`updateLPWhitelist`): +```typescript +/** + * Stub for updateLPWhitelist — some deployments may not support this + * instruction; export a placeholder so consumers can safely call it + * and bundlers don't fail on missing named exports. + */ +export async function updateLPWhitelist(args: { invoiceId: bigint; whitelist: string[] }) { + throw new Error('updateLPWhitelist is not supported by the deployed contract'); +} +``` +* **Action Needed:** Implement live transaction builder once contract endpoint is deployed. + +### 2. Governance Protocol Stubs +All stubs in `src/utils/governance.ts` are marked with `TODO` comments indicating dependencies on the upcoming governance contract deployment: +- `getProposals` (line 242) +- `castVote` (line 264) +- `delegateVotingPower` (line 286) +- `getGovTokenBalance` (line 326) +- `getQuorumThreshold` (line 427) +- `getProposalHistory` (line 444) +- `createProposal` (line 491) +- `ParameterUpdated` event logs subscription (line 625) diff --git a/docs/route-map.md b/docs/route-map.md new file mode 100644 index 0000000..ed393f1 --- /dev/null +++ b/docs/route-map.md @@ -0,0 +1,35 @@ +# ILN Route Map + +This document lists every canonical route in the Invoice Liquidity Network (ILN) Frontend, its purpose, the primary consumer, and any active redirects. + +## Canonical Routes + +| Route Path | Description | Primary Consumer | Access Type | +| :--- | :--- | :--- | :--- | +| `/` | Landing page explaining the ILN protocol and entry points | Public | Unauthenticated | +| `/freelancer` | Freelancer workspace to submit invoices and track status | Freelancer | Authenticated Wallet | +| `/payer` | Payer dashboard for viewing and settling unpaid invoices | Payer | Authenticated Wallet | +| `/lp` | Liquidity Provider dashboard for viewing and managing funded invoices | LP | Authenticated Wallet | +| `/lp/compare` | Comparison tool for comparing invoices | LP | Authenticated Wallet | +| `/marketplace` | Marketplace listing active invoices open for funding | LP / Public | Unauthenticated / Wallet | +| `/submit` | On-chain invoice submission form | Freelancer | Authenticated Wallet | +| `/governance` | Governance portal for viewing, creating, and voting on proposals | Public / Voter | Authenticated Wallet | +| `/dashboard` | Actor-agnostic dashboard overview | Active Actor | Authenticated Wallet | +| `/analytics` | Freelancer-specific performance and earnings analytics | Freelancer | Authenticated Wallet | +| `/stats` | Protocol-wide public stats (TVL, volume, yield, dispute rate) | Public | Unauthenticated | +| `/leaderboard` | Canonical protocol leaderboard for Payers, Freelancers, and LPs | Public | Unauthenticated | +| `/referrals` | Referral dashboard showing referral links and earnings stats | Public / User | Authenticated Wallet | +| `/roadmap` | Public roadmap showing product timeline | Public | Unauthenticated | +| `/offline` | PWA offline fallback page | Public | Unauthenticated | +| `/i/[id]` | Public invoice detail view | Public | Unauthenticated | +| `/pay/[id]` | Payer checkout page for settling individual invoices | Payer | Authenticated Wallet | +| `/pay/[id]/dispute` | Invoice dispute page | Payer | Authenticated Wallet | +| `/profile/[address]` | Public reputation profile and transaction activity history | Public | Unauthenticated | + +## Active Redirects + +To prevent route drift and maintain a consolidated structure, the following redirects are defined in `next.config.ts`: + +- `/dashboard/payer` → `/payer` +- `/analytics/freelancer` → `/analytics` (consolidated duplicate freelancer views) +- `/analytics/leaderboard` → `/leaderboard` (consolidated duplicate leaderboard paths) diff --git a/next.config.ts b/next.config.ts index 8120deb..aaf19c6 100644 --- a/next.config.ts +++ b/next.config.ts @@ -13,6 +13,16 @@ const nextConfig: NextConfig & { allowedDevOrigins?: string[] } = { destination: '/payer', permanent: true, }, + { + source: '/analytics/freelancer', + destination: '/analytics', + permanent: true, + }, + { + source: '/analytics/leaderboard', + destination: '/leaderboard', + permanent: true, + }, ]; }, }; diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 9fea2ca..1cc2aff 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -20,7 +20,8 @@ "governance": "Governance", "payInvoices": "Pay Invoices", "dashboard": "Dashboard", - "analytics": "Analytics", + "analytics": "My Analytics", + "stats": "Protocol Stats", "docs": "Docs" }, "landing": { diff --git a/public/locales/es/translation.json b/public/locales/es/translation.json index 05de434..8cdabe1 100644 --- a/public/locales/es/translation.json +++ b/public/locales/es/translation.json @@ -20,7 +20,8 @@ "governance": "Gobernanza", "payInvoices": "Pagar Facturas", "dashboard": "Panel", - "analytics": "Analíticas", + "analytics": "Mis Analíticas", + "stats": "Estadísticas", "docs": "Documentos" }, "landing": { diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 115e960..3fbe4e7 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -38,6 +38,7 @@ export default function Navbar() { { href: '/payer', label: t('nav.payInvoices') }, { href: '/dashboard', label: t('nav.dashboard') }, { href: '/analytics', label: t('nav.analytics') }, + { href: '/stats', label: t('nav.stats') }, { href: '/referrals', label: 'Referrals' }, ]; @@ -90,6 +91,12 @@ export default function Navbar() { > {t('nav.analytics')} + + {t('nav.stats')} + {/*