diff --git a/frontend/cmmty/components/empty-state.tsx b/frontend/cmmty/components/empty-state.tsx new file mode 100644 index 0000000..3c760fa --- /dev/null +++ b/frontend/cmmty/components/empty-state.tsx @@ -0,0 +1,20 @@ +"use client"; + +import React from "react"; +import { FileX } from "lucide-react"; + +export default function EmptyState() { + return ( +
+
+ +
+

+ No documents found +

+

+ Get started by uploading your first document. +

+
+ ); +} diff --git a/frontend/cmmty/components/pagination.tsx b/frontend/cmmty/components/pagination.tsx new file mode 100644 index 0000000..d6fdb5a --- /dev/null +++ b/frontend/cmmty/components/pagination.tsx @@ -0,0 +1,77 @@ +"use client"; + +import React from "react"; +import { ChevronLeft, ChevronRight } from "lucide-react"; + +interface PaginationProps { + currentPage: number; + totalPages: number; + onPageChange: (page: number) => void; +} + +export default function Pagination({ + currentPage, + totalPages, + onPageChange, +}: PaginationProps) { + return ( +
+
+ + +
+
+

+ Page {currentPage} of{" "} + {totalPages} +

+ +
+
+ ); +} diff --git a/frontend/cmmty/components/risk-score.tsx b/frontend/cmmty/components/risk-score.tsx new file mode 100644 index 0000000..6e77300 --- /dev/null +++ b/frontend/cmmty/components/risk-score.tsx @@ -0,0 +1,42 @@ +"use client"; + +import React from "react"; + +interface RiskScoreProps { + score?: number; +} + +export default function RiskScore({ score }: RiskScoreProps) { + if (score === undefined || score === null) { + return ; + } + + let colorClass = "text-emerald-600 dark:text-emerald-400"; + if (score >= 70) { + colorClass = "text-rose-600 dark:text-rose-400"; + } else if (score >= 40) { + colorClass = "text-amber-600 dark:text-amber-400"; + } else if (score >= 20) { + colorClass = "text-yellow-600 dark:text-yellow-400"; + } + + return ( +
+
+
= 70 + ? "bg-rose-500" + : score >= 40 + ? "bg-amber-500" + : score >= 20 + ? "bg-yellow-500" + : "bg-emerald-500" + }`} + style={{ width: `${Math.min(score, 100)}%` }} + /> +
+ {score} +
+ ); +} diff --git a/frontend/cmmty/components/status-badge.tsx b/frontend/cmmty/components/status-badge.tsx new file mode 100644 index 0000000..23b4f25 --- /dev/null +++ b/frontend/cmmty/components/status-badge.tsx @@ -0,0 +1,49 @@ +"use client"; + +import React from "react"; +import { DocumentStatus } from "../types/document"; + +interface StatusBadgeProps { + status: DocumentStatus; +} + +const statusConfig: Record< + DocumentStatus, + { label: string; className: string } +> = { + [DocumentStatus.PENDING]: { + label: "Pending", + className: + "bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-300", + }, + [DocumentStatus.ANALYZING]: { + label: "Analyzing", + className: + "bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300", + }, + [DocumentStatus.VERIFIED]: { + label: "Verified", + className: + "bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-300", + }, + [DocumentStatus.FLAGGED]: { + label: "Flagged", + className: + "bg-rose-100 text-rose-800 dark:bg-rose-900/30 dark:text-rose-300", + }, + [DocumentStatus.REJECTED]: { + label: "Rejected", + className: "bg-gray-200 text-gray-800 dark:bg-gray-800 dark:text-gray-300", + }, +}; + +export default function StatusBadge({ status }: StatusBadgeProps) { + const config = statusConfig[status]; + return ( + + {config.label} + + ); +} diff --git a/frontend/cmmty/lib/data.ts b/frontend/cmmty/lib/data.ts new file mode 100644 index 0000000..7a098f5 --- /dev/null +++ b/frontend/cmmty/lib/data.ts @@ -0,0 +1,172 @@ +import { Document, DocumentStatus } from "../types/document"; + +export const mockDocuments: Document[] = [ + { + id: "1", + ownerId: "user-1", + title: "Land Deed - Plot 42A Nairobi", + filePath: "/uploads/deed_42a.pdf", + fileHash: "a1b2c3d4e5f6", + fileSize: 2457600, + mimeType: "application/pdf", + status: DocumentStatus.VERIFIED, + riskScore: 12, + riskFlags: [], + createdAt: "2026-04-10T08:30:00Z", + updatedAt: "2026-04-12T14:20:00Z", + }, + { + id: "2", + ownerId: "user-1", + title: "Title Certificate - Mombasa Region", + filePath: "/uploads/title_mombasa.pdf", + fileHash: "b2c3d4e5f6g7", + fileSize: 1892000, + mimeType: "application/pdf", + status: DocumentStatus.FLAGGED, + riskScore: 78, + riskFlags: ["duplicate_claim", "boundary_dispute"], + createdAt: "2026-04-08T11:15:00Z", + updatedAt: "2026-04-11T09:45:00Z", + }, + { + id: "3", + ownerId: "user-1", + title: "Survey Plan - Kisumu Township", + filePath: "/uploads/survey_kisumu.pdf", + fileHash: "c3d4e5f6g7h8", + fileSize: 3200000, + mimeType: "application/pdf", + status: DocumentStatus.PENDING, + riskScore: 0, + riskFlags: [], + createdAt: "2026-04-15T16:00:00Z", + updatedAt: "2026-04-15T16:00:00Z", + }, + { + id: "4", + ownerId: "user-1", + title: "Lease Agreement - Plot 12B", + filePath: "/uploads/lease_12b.pdf", + fileHash: "d4e5f6g7h8i9", + fileSize: 1560000, + mimeType: "application/pdf", + status: DocumentStatus.ANALYZING, + riskScore: 35, + riskFlags: ["encoding_issue"], + createdAt: "2026-04-14T10:30:00Z", + updatedAt: "2026-04-16T08:15:00Z", + }, + { + id: "5", + ownerId: "user-1", + title: "Land Transfer Form - Eldoret", + filePath: "/uploads/transfer_eldoret.pdf", + fileHash: "e5f6g7h8i9j0", + fileSize: 2100000, + mimeType: "application/pdf", + status: DocumentStatus.REJECTED, + riskScore: 92, + riskFlags: ["forged_signature", "invalid_notary"], + createdAt: "2026-04-05T09:00:00Z", + updatedAt: "2026-04-07T11:30:00Z", + }, + { + id: "6", + ownerId: "user-1", + title: "Property Tax Receipt 2026", + filePath: "/uploads/tax_receipt_2026.pdf", + fileHash: "f6g7h8i9j0k1", + fileSize: 890000, + mimeType: "application/pdf", + status: DocumentStatus.VERIFIED, + riskScore: 5, + riskFlags: [], + createdAt: "2026-04-01T07:45:00Z", + updatedAt: "2026-04-02T10:00:00Z", + }, + { + id: "7", + ownerId: "user-1", + title: "Boundary Dispute Resolution", + filePath: "/uploads/boundary_resolution.pdf", + fileHash: "g7h8i9j0k1l2", + fileSize: 2750000, + mimeType: "application/pdf", + status: DocumentStatus.FLAGGED, + riskScore: 65, + riskFlags: ["boundary_dispute"], + createdAt: "2026-04-12T13:20:00Z", + updatedAt: "2026-04-13T15:10:00Z", + }, + { + id: "8", + ownerId: "user-1", + title: "Coastal Zone Land Permit", + filePath: "/uploads/coastal_permit.pdf", + fileHash: "h8i9j0k1l2m3", + fileSize: 1340000, + mimeType: "application/pdf", + status: DocumentStatus.PENDING, + riskScore: 0, + riskFlags: [], + createdAt: "2026-04-18T08:00:00Z", + updatedAt: "2026-04-18T08:00:00Z", + }, + { + id: "9", + ownerId: "user-1", + title: "Inheritance Declaration - Nakuru", + filePath: "/uploads/inheritance_nakuru.pdf", + fileHash: "i9j0k1l2m3n4", + fileSize: 1980000, + mimeType: "application/pdf", + status: DocumentStatus.ANALYZING, + riskScore: 42, + riskFlags: ["missing_heir"], + createdAt: "2026-04-13T11:00:00Z", + updatedAt: "2026-04-16T14:30:00Z", + }, + { + id: "10", + ownerId: "user-1", + title: "Mortgage Agreement - ABC Bank", + filePath: "/uploads/mortgage_abc.pdf", + fileHash: "j0k1l2m3n4o5", + fileSize: 2560000, + mimeType: "application/pdf", + status: DocumentStatus.VERIFIED, + riskScore: 18, + riskFlags: [], + createdAt: "2026-03-28T09:30:00Z", + updatedAt: "2026-04-01T10:15:00Z", + }, + { + id: "11", + ownerId: "user-1", + title: "Subdivision Approval - Kitale", + filePath: "/uploads/subdivision_kitale.pdf", + fileHash: "k1l2m3n4o5p6", + fileSize: 3100000, + mimeType: "application/pdf", + status: DocumentStatus.PENDING, + riskScore: 0, + riskFlags: [], + createdAt: "2026-04-20T07:00:00Z", + updatedAt: "2026-04-20T07:00:00Z", + }, + { + id: "12", + ownerId: "user-1", + title: "Environmental Impact Assessment", + filePath: "/uploads/eia_report.pdf", + fileHash: "l2m3n4o5p6q7", + fileSize: 4500000, + mimeType: "application/pdf", + status: DocumentStatus.FLAGGED, + riskScore: 58, + riskFlags: ["expired_permit"], + createdAt: "2026-04-09T12:00:00Z", + updatedAt: "2026-04-11T16:45:00Z", + }, +]; diff --git a/frontend/cmmty/types/document.ts b/frontend/cmmty/types/document.ts new file mode 100644 index 0000000..14925fc --- /dev/null +++ b/frontend/cmmty/types/document.ts @@ -0,0 +1,22 @@ +export enum DocumentStatus { + PENDING = "pending", + ANALYZING = "analyzing", + VERIFIED = "verified", + FLAGGED = "flagged", + REJECTED = "rejected", +} + +export interface Document { + id: string; + ownerId: string; + title: string; + filePath: string; + fileHash: string; + fileSize: number; + mimeType: string; + status: DocumentStatus; + riskScore?: number; + riskFlags?: string[]; + createdAt: string; + updatedAt: string; +}