From 51c7d280b0eee3b0f8abb78177c1416aa5f132a5 Mon Sep 17 00:00:00 2001 From: Yaseen Date: Fri, 10 Jul 2026 09:16:01 +0530 Subject: [PATCH] implement global UI components including Toast notification system, PageLayout, and Modal utilities while migrating existing pages to the new layout architecture --- Channel-Backend/prisma/schema.prisma | 19 +- .../src/controllers/legal.controller.ts | 9 +- Channel-Backend/src/services/legal.service.ts | 23 +- Channel-Frontend/src/App.tsx | 6 +- .../src/app/layouts/AdminLayout.tsx | 206 +++-- .../src/app/layouts/ClientLayout.tsx | 16 +- Channel-Frontend/src/app/router/index.tsx | 128 ++- .../src/components/layout/PageLayout.tsx | 47 + Channel-Frontend/src/components/ui/Button.tsx | 45 + .../components/ui/DocumentPreviewModal.tsx | 679 ++++++++++++++ Channel-Frontend/src/components/ui/Modal.tsx | 93 ++ Channel-Frontend/src/components/ui/Toast.tsx | 122 +++ .../components/AnalyticsDashboard.tsx | 313 ------- .../assets/components/AssetDetailsModal.tsx | 179 ++-- .../assets/components/AssetExplorer.tsx | 22 +- .../assets/components/AssetViewerModal.tsx | 373 ++++---- .../components/DownloadRequestsModal.tsx | 128 ++- .../assets/components/EditAssetModal.tsx | 256 +++--- .../assets/components/ShareAssetModal.tsx | 247 +++--- .../assets/components/UploadAssetModal.tsx | 552 ++++++------ .../features/blog/components/BlogCatalog.tsx | 490 ++++++----- Channel-Frontend/src/hooks/use-legal-query.ts | 16 +- Channel-Frontend/src/hooks/use-toast.ts | 1 + Channel-Frontend/src/pages/AssetsPage.tsx | 338 ++++--- .../src/pages/ClientAgreementsPage.tsx | 308 +++++++ Channel-Frontend/src/pages/DashboardPage.tsx | 129 +-- Channel-Frontend/src/pages/InvitePage.tsx | 33 +- Channel-Frontend/src/pages/LoginPage.tsx | 258 ++++-- Channel-Frontend/src/pages/OnboardingPage.tsx | 15 +- .../src/pages/admin/ApprovalsPage.tsx | 344 +++++--- .../src/pages/admin/DirectoryPage.tsx | 833 ++++++++++-------- .../src/pages/admin/LegalTemplatesPage.tsx | 100 ++- Channel-Frontend/src/services/legal-api.ts | 12 + 33 files changed, 3904 insertions(+), 2436 deletions(-) create mode 100644 Channel-Frontend/src/components/layout/PageLayout.tsx create mode 100644 Channel-Frontend/src/components/ui/Button.tsx create mode 100644 Channel-Frontend/src/components/ui/DocumentPreviewModal.tsx create mode 100644 Channel-Frontend/src/components/ui/Modal.tsx create mode 100644 Channel-Frontend/src/components/ui/Toast.tsx delete mode 100644 Channel-Frontend/src/features/admin-analytics/components/AnalyticsDashboard.tsx create mode 100644 Channel-Frontend/src/hooks/use-toast.ts create mode 100644 Channel-Frontend/src/pages/ClientAgreementsPage.tsx diff --git a/Channel-Backend/prisma/schema.prisma b/Channel-Backend/prisma/schema.prisma index cced4cb..d84ee8e 100644 --- a/Channel-Backend/prisma/schema.prisma +++ b/Channel-Backend/prisma/schema.prisma @@ -117,15 +117,16 @@ model LegalDocument { } model LegalAcceptance { - id String @id @default(uuid()) - docId String - userId String - ipAddress String - signatureHash String? - documentUrl String? - acceptedAt DateTime @default(now()) - document LegalDocument @relation(fields: [docId], references: [id]) - user User @relation(fields: [userId], references: [id]) + id String @id @default(uuid()) + docId String + userId String + ipAddress String + signatureHash String? + documentUrl String? + signatureBase64 String? + acceptedAt DateTime @default(now()) + document LegalDocument @relation(fields: [docId], references: [id]) + user User @relation(fields: [userId], references: [id]) } model AuditLog { diff --git a/Channel-Backend/src/controllers/legal.controller.ts b/Channel-Backend/src/controllers/legal.controller.ts index 055a730..5b13872 100644 --- a/Channel-Backend/src/controllers/legal.controller.ts +++ b/Channel-Backend/src/controllers/legal.controller.ts @@ -69,7 +69,14 @@ export class LegalController { signatureHash = crypto.createHash('sha256').update(signatureBase64).digest('hex'); } - const acceptance = await this.legalService.recordAcceptance(activeDoc.id, userId, ipAddress, signatureHash || undefined, documentUrl); + const acceptance = await this.legalService.recordAcceptance( + activeDoc.id, + userId, + ipAddress, + signatureHash || undefined, + documentUrl, + signatureBase64 || undefined + ); // Check if they completed all onboarding steps await this.legalService.checkOnboardingCompletion(userId); diff --git a/Channel-Backend/src/services/legal.service.ts b/Channel-Backend/src/services/legal.service.ts index 4087755..d9d30fe 100644 --- a/Channel-Backend/src/services/legal.service.ts +++ b/Channel-Backend/src/services/legal.service.ts @@ -33,10 +33,11 @@ export class LegalService { ipAddress: string, signatureHash?: string, documentUrl?: string, + signatureBase64?: string, ) { // Record acceptance const acceptance = await prisma.legalAcceptance.create({ - data: { docId, userId, ipAddress, signatureHash, documentUrl }, + data: { docId, userId, ipAddress, signatureHash, documentUrl, signatureBase64 }, }); return acceptance; @@ -67,7 +68,15 @@ export class LegalService { public async getAcceptances(userId: string) { return await prisma.legalAcceptance.findMany({ where: { userId }, - include: { document: true }, + select: { + id: true, + signatureHash: true, + documentUrl: true, + signatureBase64: true, + ipAddress: true, + acceptedAt: true, + document: true, + }, }); } @@ -79,7 +88,15 @@ export class LegalService { email: true, createdAt: true, acceptances: { - include: { document: true } + select: { + id: true, + signatureHash: true, + documentUrl: true, + signatureBase64: true, + ipAddress: true, + acceptedAt: true, + document: true, + } } } }); diff --git a/Channel-Frontend/src/App.tsx b/Channel-Frontend/src/App.tsx index 6d993cc..e0bf817 100644 --- a/Channel-Frontend/src/App.tsx +++ b/Channel-Frontend/src/App.tsx @@ -5,6 +5,8 @@ import { useEffect } from 'react'; import { useThemeStore } from './hooks/use-theme'; import { useAuthStore } from './hooks/use-auth'; +import { ToastProvider } from "./components/ui/Toast"; + const queryClient = new QueryClient({ defaultOptions: { queries: { retry: 1, refetchOnWindowFocus: false } @@ -39,7 +41,9 @@ export const App = () => { return ( - + + + ); }; diff --git a/Channel-Frontend/src/app/layouts/AdminLayout.tsx b/Channel-Frontend/src/app/layouts/AdminLayout.tsx index 141a90a..491e0d2 100644 --- a/Channel-Frontend/src/app/layouts/AdminLayout.tsx +++ b/Channel-Frontend/src/app/layouts/AdminLayout.tsx @@ -1,9 +1,22 @@ -import React, { useState } from 'react'; -import { Link, Outlet, useLocation, useNavigate } from 'react-router-dom'; -import { useThemeStore } from '../../hooks/use-theme'; -import { useAuthStore } from '../../hooks/use-auth'; -import { ShieldCheck, BarChart3, ClipboardCheck, FolderGit2, BookCopy, Users, LogOut, Menu, X, Sun, Moon, ChevronRight, ChevronLeft } from 'lucide-react'; -import { motion, AnimatePresence } from 'framer-motion'; +import React, { useState } from "react"; +import { Link, Outlet, useLocation, useNavigate } from "react-router-dom"; +import { useThemeStore } from "../../hooks/use-theme"; +import { useAuthStore } from "../../hooks/use-auth"; +import { + ShieldCheck, + ClipboardCheck, + FolderGit2, + BookCopy, + Users, + LogOut, + Menu, + X, + Sun, + Moon, + ChevronRight, + ChevronLeft, +} from "lucide-react"; +import { motion, AnimatePresence } from "framer-motion"; export const AdminLayout: React.FC = () => { const { user, logout } = useAuthStore(); @@ -15,51 +28,62 @@ export const AdminLayout: React.FC = () => { const handleLogout = () => { logout(); - navigate('/login'); + navigate("/login"); }; const navItems = [ - { name: 'Partners', path: '/admin/partners', icon: Users }, - { name: 'Approvals Queue', path: '/admin/approvals', icon: ClipboardCheck }, - { name: 'Legal Templates', path: '/admin/legal', icon: ShieldCheck }, - { name: 'Manage Catalog', path: '/admin/assets', icon: FolderGit2 }, - { name: 'Analytics', path: '/admin/analytics', icon: BarChart3 }, - { name: 'Blog CMS', path: '/admin/blog', icon: BookCopy } + { name: "Partners", path: "/admin/partners", icon: Users }, + { name: "Approvals Queue", path: "/admin/approvals", icon: ClipboardCheck }, + { name: "Legal Templates", path: "/admin/legal", icon: ShieldCheck }, + { name: "Manage Catalog", path: "/admin/assets", icon: FolderGit2 }, + { name: "Blog CMS", path: "/admin/blog", icon: BookCopy }, ]; return (
- {/* ── Desktop Sidebar ── */} - - - {/* ── Main Content Area ── */} -
+ {/* ── Main Content Area ── */} +
{/* Ambient Glow */}
{/* Mobile Header */} -
+
@@ -161,7 +159,7 @@ export const ClientLayout: React.FC = () => { ))}
- @@ -171,13 +169,13 @@ export const ClientLayout: React.FC = () => { )} -
+
{/* Footer */} -