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 ── */}
-