diff --git a/src/app/admin/roles/page.tsx b/src/app/admin/roles/page.tsx index 922a69e..101905d 100644 --- a/src/app/admin/roles/page.tsx +++ b/src/app/admin/roles/page.tsx @@ -39,7 +39,7 @@ const buildDefaultGroups = (): PermissionGroup[] => [ { id: 'kyc', title: 'KYC Requests & Verification', - description: 'The Biker user will request from the app. Investor, Shop, Merchant will request from the website. Front desk officers (hub/head office) can request for Biker, Investor, Shop, Merchant and can upload remaining documents. Admin officers (head office) will approve or reject documents with notes and "make a Biker | Investor | Shop | Merchant".', + description: 'The Biker user will request from the app. Investor, Swap Station, Merchant will request from the website. Front desk officers (hub/head office) can request for Biker, Investor, Swap Station, Merchant and can upload remaining documents. Admin officers (head office) will approve or reject documents with notes and "make a Biker | Investor | Swap Station | Merchant".', icon: FileSearch, permissions: [ { key: 'kyc.request', label: 'KYC Request', enabled: false }, @@ -47,7 +47,7 @@ const buildDefaultGroups = (): PermissionGroup[] => [ { key: 'kyc.doc_upload', label: 'Document Upload', enabled: false }, { key: 'kyc.doc_approve', label: 'Document Approve', enabled: false }, { key: 'kyc.doc_reject', label: 'Document Reject', enabled: false }, - { key: 'kyc.make_valid_user', label: 'Make a Biker | Make an Investor | Make a Shop | Make a Merchant', enabled: false }, + { key: 'kyc.make_valid_user', label: 'Make a Biker | Make an Investor | Make a Swap Station | Make a Merchant', enabled: false }, ] }, { diff --git a/src/app/admin/settings/components/BrandingSettings.tsx b/src/app/admin/settings/components/BrandingSettings.tsx new file mode 100644 index 0000000..6871fc4 --- /dev/null +++ b/src/app/admin/settings/components/BrandingSettings.tsx @@ -0,0 +1,119 @@ +'use client'; + +import { Image, Camera, Ruler } from 'lucide-react'; +import { CompanySettings } from '../page'; + +interface BrandingSettingsProps { + settings: CompanySettings; + setSettings: React.Dispatch>; +} + +export default function BrandingSettings({ settings, setSettings }: BrandingSettingsProps) { + return ( +
+

Branding & Design

+ +
+
+ +
+ +

Upload Logo (PNG, SVG)

+

Recommended: 200x50px

+
+
+
+ +
+ +

Upload Favicon

+

Recommended: 32x32px

+
+
+
+ +
+
+ +
+ setSettings({ ...settings, primaryColor: e.target.value })} + className="w-12 h-12 rounded-lg cursor-pointer border-0" + /> + setSettings({ ...settings, primaryColor: e.target.value })} + className="flex-1 px-3 py-2 border border-slate-200 rounded-lg text-sm" + /> +
+
+
+ +
+ setSettings({ ...settings, secondaryColor: e.target.value })} + className="w-12 h-12 rounded-lg cursor-pointer border-0" + /> + setSettings({ ...settings, secondaryColor: e.target.value })} + className="flex-1 px-3 py-2 border border-slate-200 rounded-lg text-sm" + /> +
+
+
+ +
+ +
+ + setSettings({ ...settings, borderRadius: parseInt(e.target.value) })} + className="flex-1" + /> + {settings.borderRadius}px +
+
+ {[4, 8, 12, 16].map(radius => ( + + ))} +
+
+ +
+ +
+
+ Primary +
+
+ Secondary +
+
+
+
+ ); +} diff --git a/src/app/admin/settings/components/CompanyPolicySettings.tsx b/src/app/admin/settings/components/CompanyPolicySettings.tsx new file mode 100644 index 0000000..97b38ec --- /dev/null +++ b/src/app/admin/settings/components/CompanyPolicySettings.tsx @@ -0,0 +1,349 @@ +'use client'; + +import { Plus, Pencil, Trash2 } from 'lucide-react'; +import RichTextEditor from '@/components/RichTextEditor'; +import { CompanySettings } from '../page'; + +interface CompanyPolicySettingsProps { + settings: CompanySettings; + setSettings: React.Dispatch>; + activeMasterTab: 'investor' | 'merchant' | 'swapstation' | 'rentalType'; + setActiveMasterTab: (tab: 'investor' | 'merchant' | 'swapstation' | 'rentalType') => void; + activeRentalTypeTab: 'single' | 'shared' | 'renttoown'; + setActiveRentalTypeTab: (tab: 'single' | 'shared' | 'renttoown') => void; + editingPolicy: { tab: string; index: number } | null; + setEditingPolicy: (policy: { tab: string; index: number } | null) => void; + editPolicyName: string; + setEditPolicyName: (name: string) => void; + editPolicyDesc: string; + setEditPolicyDesc: (desc: string) => void; + editPolicyDescHtml: string; + setEditPolicyDescHtml: (desc: string) => void; + showAddPolicy: boolean; + setShowAddPolicy: (show: boolean) => void; + newPolicyName: string; + setNewPolicyName: (name: string) => void; + newPolicyDesc: string; + setNewPolicyDesc: (desc: string) => void; +} + +export default function CompanyPolicySettings({ + settings, + setSettings, + activeMasterTab, + setActiveMasterTab, + activeRentalTypeTab, + setActiveRentalTypeTab, + editingPolicy, + setEditingPolicy, + editPolicyName, + setEditPolicyName, + editPolicyDesc, + setEditPolicyDesc, + editPolicyDescHtml, + setEditPolicyDescHtml, + showAddPolicy, + setShowAddPolicy, + newPolicyName, + setNewPolicyName, + newPolicyDesc, + setNewPolicyDesc, +}: CompanyPolicySettingsProps) { + return ( +
+

Company's Policy

+ +
+ + + + +
+ + {activeMasterTab === 'investor' && ( +
+
+ + +
+ {showAddPolicy && ( +
+ setNewPolicyName(e.target.value)} className="w-full px-2 py-1.5 border border-slate-200 rounded text-sm mb-2" placeholder="Policy Title" /> + setNewPolicyDesc(val)} placeholder="Policy Description..." minHeight={100} /> +
+ + +
+
+ )} +
+ {(settings.companyPolicy?.investor || []).map((policy, i) => ( +
+ {editingPolicy?.tab === 'investor' && editingPolicy?.index === i ? ( +
+ setEditPolicyName(e.target.value)} className="w-full px-2 py-1.5 border border-slate-200 rounded text-sm" placeholder="Policy Title" /> + setEditPolicyDescHtml(val)} placeholder="Policy Description..." minHeight={100} /> +
+ + +
+
+ ) : ( +
+
+
+ {policy.title} +
+
+
+
+ + +
+
+ )} +
+ ))} +
+
+ )} + + {activeMasterTab === 'merchant' && ( +
+
+ + +
+ {showAddPolicy && ( +
+ setNewPolicyName(e.target.value)} className="w-full px-2 py-1.5 border border-slate-200 rounded text-sm mb-2" placeholder="Policy Title" /> + setNewPolicyDesc(val)} placeholder="Policy Description..." minHeight={100} /> +
+ + +
+
+ )} +
+ {(settings.companyPolicy?.merchant || []).map((policy, i) => ( +
+ {editingPolicy?.tab === 'merchant' && editingPolicy?.index === i ? ( +
+ setEditPolicyName(e.target.value)} className="w-full px-2 py-1.5 border border-slate-200 rounded text-sm" placeholder="Policy Title" /> + setEditPolicyDescHtml(val)} placeholder="Policy Description..." minHeight={100} /> +
+ + +
+
+ ) : ( +
+
+
+ {policy.title} +
+
+
+
+ + +
+
+ )} +
+ ))} +
+
+ )} + + {activeMasterTab === 'swapstation' && ( +
+
+ + +
+ {showAddPolicy && ( +
+ setNewPolicyName(e.target.value)} className="w-full px-2 py-1.5 border border-slate-200 rounded text-sm mb-2" placeholder="Policy Title" /> + setNewPolicyDesc(val)} placeholder="Policy Description..." minHeight={100} /> +
+ + +
+
+ )} +
+ {(settings.companyPolicy?.swapStation || []).map((policy, i) => ( +
+ {editingPolicy?.tab === 'swapstation' && editingPolicy?.index === i ? ( +
+ setEditPolicyName(e.target.value)} className="w-full px-2 py-1.5 border border-slate-200 rounded text-sm" placeholder="Policy Title" /> + setEditPolicyDescHtml(val)} placeholder="Policy Description..." minHeight={100} /> +
+ + +
+
+ ) : ( +
+
+
+ {policy.title} +
+
+
+
+ + +
+
+ )} +
+ ))} +
+
+ )} + + {activeMasterTab === 'rentalType' && ( +
+
+ + + +
+ +
+ + +
+ {showAddPolicy && ( +
+ setNewPolicyName(e.target.value)} className="w-full px-2 py-1.5 border border-slate-200 rounded text-sm mb-2" placeholder="Policy Title" /> + setNewPolicyDesc(val)} placeholder="Policy Description..." minHeight={100} /> +
+ + +
+
+ )} +
+ {(settings.companyPolicy?.rentalTypes[activeRentalTypeTab] || []).map((policy, i) => ( +
+ {editingPolicy?.tab === 'rentalType' && editingPolicy?.index === i ? ( +
+ setEditPolicyName(e.target.value)} className="w-full px-2 py-1.5 border border-slate-200 rounded text-sm" placeholder="Policy Title" /> + setEditPolicyDescHtml(val)} placeholder="Policy Description..." minHeight={100} /> +
+ + +
+
+ ) : ( +
+
+
+ {policy.title} +
+
+
+
+ + +
+
+ )} +
+ ))} +
+
+ )} +
+ ); +} diff --git a/src/app/admin/settings/components/GeneralSettings.tsx b/src/app/admin/settings/components/GeneralSettings.tsx new file mode 100644 index 0000000..560f2f6 --- /dev/null +++ b/src/app/admin/settings/components/GeneralSettings.tsx @@ -0,0 +1,171 @@ +'use client'; + +import { Upload } from 'lucide-react'; +import { CompanySettings } from '../page'; + +interface GeneralSettingsProps { + settings: CompanySettings; + setSettings: React.Dispatch>; +} + +export default function GeneralSettings({ settings, setSettings }: GeneralSettingsProps) { + return ( +
+

General Information

+ +
+
+ + setSettings({ ...settings, name: e.target.value })} + className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" + /> +
+
+ + setSettings({ ...settings, shortName: e.target.value })} + className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" + /> +
+
+ + setSettings({ ...settings, tagLine: e.target.value })} + className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" + /> +
+
+ + setSettings({ ...settings, website: e.target.value })} + className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" + /> +
+
+ +
+ +