Files
auditly/src/pages/Settings.tsx

297 lines
22 KiB
TypeScript

import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTheme } from '../contexts/ThemeContext';
import { useAuth } from '../contexts/AuthContext';
import Sidebar from '../components/figma/Sidebar';
import { Button } from '../components/UiKit';
import { Theme } from '../types';
interface UserProfile {
fullName: string;
email: string;
profilePicture?: string;
}
type ThemeMode = 'system' | 'light' | 'dark';
const SettingsNew: React.FC = () => {
const { theme, setTheme } = useTheme();
const { user } = useAuth();
const navigate = useNavigate();
const [activeTab, setActiveTab] = useState<'general' | 'billing'>('general');
const [userProfile, setUserProfile] = useState<UserProfile>({
fullName: 'John Doe',
email: 'Johndoe1234@gmail.com'
});
const [selectedTheme, setSelectedTheme] = useState<ThemeMode>('light');
const handleProfileUpdate = (field: keyof UserProfile, value: string) => {
setUserProfile(prev => ({
...prev,
[field]: value
}));
};
const handlePhotoUpload = () => {
// In a real app, this would open a file picker
alert('Photo upload functionality would be implemented here');
};
const handleSaveChanges = () => {
// In a real app, this would save to backend
alert('Settings saved successfully!');
};
const handleReset = () => {
setUserProfile({
fullName: 'John Doe',
email: 'Johndoe1234@gmail.com'
});
setSelectedTheme('light');
};
if (!user) {
navigate('/login');
return null;
}
return (
<div className="flex-1 self-stretch shadow-[0px_0px_15px_0px_rgba(0,0,0,0.08)] flex justify-between items-start h-full">
<Sidebar companyName="Zitlac Media" />
<div className="flex-1 self-stretch bg-[--Neutrals-NeutralSlate0] inline-flex flex-col justify-start items-start">
{/* Tab Navigation */}
<div className="self-stretch px-6 pt-6 border-b border-[--Neutrals-NeutralSlate200] flex flex-col justify-start items-end">
<div className="self-stretch inline-flex justify-start items-start gap-6">
<div
onClick={() => setActiveTab('general')}
className={`w-32 inline-flex flex-col justify-start items-start gap-3 cursor-pointer ${activeTab === 'general' ? '' : 'opacity-60'
}`}
>
<div className={`self-stretch text-center justify-center text-base font-['Inter'] leading-normal ${activeTab === 'general'
? 'text-Text-Gray-800 font-semibold'
: 'text-Text-Gray-500 font-normal'
}`}>
General Settings
</div>
{activeTab === 'general' && (
<div className="self-stretch h-0.5 bg-[--Neutrals-NeutralSlate800] rounded-tl-lg rounded-tr-lg" />
)}
</div>
<div
onClick={() => setActiveTab('billing')}
className={`inline-flex flex-col justify-start items-start gap-3 cursor-pointer ${activeTab === 'billing' ? '' : 'opacity-60'
}`}
>
<div className={`text-center justify-center text-base font-['Inter'] leading-normal ${activeTab === 'billing'
? 'text-Text-Gray-800 font-semibold'
: 'text-Text-Gray-500 font-normal'
}`}>
Plan & Billings
</div>
{activeTab === 'billing' && (
<div className="w-24 h-0.5 bg-[--Neutrals-NeutralSlate800] rounded-tl-lg rounded-tr-lg" />
)}
</div>
</div>
<div className="w-24 h-0.5 opacity-0 bg-[--Neutrals-NeutralSlate800] rounded-tl-lg rounded-tr-lg" />
</div>
{/* General Settings Content */}
{activeTab === 'general' && (
<>
{/* Profile Information Section */}
<div className="w-full h-72 p-6 flex flex-col justify-start items-start gap-6">
<div className="flex flex-col justify-start items-start gap-1">
<div className="self-stretch justify-start text-[--Neutrals-NeutralSlate800] text-lg font-semibold font-['Inter'] leading-7">Profile Information</div>
<div className="self-stretch justify-start text-[--Neutrals-NeutralSlate500] text-sm font-normal font-['Inter'] leading-tight">Update your personal details, and keep your profile up to date.</div>
</div>
<div className="self-stretch flex flex-col justify-start items-start gap-6">
{/* Profile Picture Section */}
<div className="w-[664px] px-3 py-2.5 bg-[--Neutrals-NeutralSlate0] rounded-2xl outline outline-1 outline-offset-[-1px] outline-[--Neutrals-NeutralSlate200] inline-flex justify-between items-center">
<div className="flex-1 flex justify-start items-center gap-3">
<div className="w-14 h-14 relative bg-red-200 rounded-[999px]">
<div>
<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_1042_3786)">
<ellipse cx="28" cy="54.6008" rx="22.4" ry="16.8" fill="white" fillOpacity="0.72" />
<circle opacity="0.9" cx="28" cy="22.3992" r="11.2" fill="white" />
</g>
<defs>
<clipPath id="clip0_1042_3786">
<rect width="56" height="56" rx="28" fill="white" />
</clipPath>
</defs>
</svg>
</div>
</div>
<div className="flex-1 inline-flex flex-col justify-start items-start gap-1">
<div className="self-stretch justify-center text-[--Neutrals-NeutralSlate800] text-base font-semibold font-['Inter'] leading-normal">Profile Picture</div>
<div className="self-stretch justify-center text-[--Neutrals-NeutralSlate500] text-xs font-normal font-['Inter'] leading-none">PNG, JPEG, GIF Under 10MB</div>
</div>
</div>
<div
onClick={handlePhotoUpload}
className="px-3 py-2.5 bg-[--Neutrals-NeutralSlate100] rounded-[999px] flex justify-center items-center gap-1 overflow-hidden cursor-pointer hover:bg-[--Neutrals-NeutralSlate100]"
>
<div>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.66665 10.8282C1.86266 10.29 1.33331 9.37347 1.33331 8.33333C1.33331 6.77095 2.52765 5.48753 4.05314 5.34625C4.36519 3.44809 6.01348 2 7.99998 2C9.98648 2 11.6348 3.44809 11.9468 5.34625C13.4723 5.48753 14.6666 6.77095 14.6666 8.33333C14.6666 9.37347 14.1373 10.29 13.3333 10.8282M5.33331 10.6667L7.99998 8M7.99998 8L10.6666 10.6667M7.99998 8V14" stroke="var(--Neutrals-NeutralSlate950)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</div>
<div className="px-1 flex justify-center items-center">
<div className="justify-center text-[--Neutrals-NeutralSlate950] text-sm font-medium font-['Inter'] leading-tight">Upload Photo</div>
</div>
</div>
</div>
{/* Name and Email Fields */}
<div className="w-[664px] inline-flex justify-start items-center gap-4">
<div className="flex-1 inline-flex flex-col justify-start items-start gap-2">
<div className="self-stretch inline-flex justify-start items-center gap-0.5">
<div className="justify-start text-[--Neutrals-NeutralSlate900] text-sm font-normal font-['Inter'] leading-tight">Full Name</div>
</div>
<div className="self-stretch flex flex-col justify-start items-start gap-1">
<div className="self-stretch px-4 py-3.5 bg-[--Neutrals-NeutralSlate100] rounded-[999px] inline-flex justify-start items-center gap-2 overflow-hidden">
<div>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 12.5C7.35828 12.5 5.00901 13.7755 3.51334 15.755C3.19143 16.181 3.03047 16.394 3.03574 16.6819C3.03981 16.9043 3.17948 17.1849 3.35448 17.3222C3.581 17.5 3.8949 17.5 4.5227 17.5H15.4773C16.1051 17.5 16.419 17.5 16.6455 17.3222C16.8205 17.1849 16.9602 16.9043 16.9643 16.6819C16.9695 16.394 16.8086 16.181 16.4867 15.755C14.991 13.7755 12.6417 12.5 10 12.5Z" stroke="var(--Neutrals-NeutralSlate600)" strokeWidth="1.5" strokeMiterlimit="10" strokeLinecap="round" strokeLinejoin="round" />
<path d="M10 10C12.0711 10 13.75 8.32107 13.75 6.25C13.75 4.17893 12.0711 2.5 10 2.5C7.92894 2.5 6.25001 4.17893 6.25001 6.25C6.25001 8.32107 7.92894 10 10 10Z" stroke="var(--Neutrals-NeutralSlate600)" strokeWidth="1.5" strokeMiterlimit="10" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</div>
<input
type="text"
value={userProfile.fullName}
onChange={(e) => handleProfileUpdate('fullName', e.target.value)}
className="flex-1 bg-transparent text-[--Neutrals-NeutralSlate950] text-sm font-normal font-['Inter'] leading-tight outline-none"
/>
</div>
</div>
</div>
<div className="flex-1 inline-flex flex-col justify-start items-start gap-2">
<div className="self-stretch inline-flex justify-start items-center gap-0.5">
<div className="justify-start text-[--Neutrals-NeutralSlate900] text-sm font-normal font-['Inter'] leading-tight">Email Address</div>
</div>
<div className="self-stretch flex flex-col justify-start items-start gap-1">
<div className="self-stretch px-4 py-3.5 bg-[--Neutrals-NeutralSlate100] rounded-[999px] inline-flex justify-start items-center gap-2 overflow-hidden">
<div>
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.66669 5.83203L8.47079 10.5949C9.02176 10.9806 9.29725 11.1734 9.59691 11.2481C9.8616 11.3141 10.1384 11.3141 10.4031 11.2481C10.7028 11.1734 10.9783 10.9806 11.5293 10.5949L18.3334 5.83203M5.66669 16.6654H14.3334C15.7335 16.6654 16.4336 16.6654 16.9683 16.3929C17.4387 16.1532 17.8212 15.7707 18.0609 15.3003C18.3334 14.7656 18.3334 14.0655 18.3334 12.6654V7.33203C18.3334 5.9319 18.3334 5.23183 18.0609 4.69705C17.8212 4.22665 17.4387 3.8442 16.9683 3.60451C16.4336 3.33203 15.7335 3.33203 14.3334 3.33203H5.66669C4.26656 3.33203 3.56649 3.33203 3.03171 3.60451C2.56131 3.8442 2.17885 4.22665 1.93917 4.69705C1.66669 5.23183 1.66669 5.9319 1.66669 7.33203V12.6654C1.66669 14.0655 1.66669 14.7656 1.93917 15.3003C2.17885 15.7707 2.56131 16.1532 3.03171 16.3929C3.56649 16.6654 4.26656 16.6654 5.66669 16.6654Z" stroke="var(--Neutrals-NeutralSlate600)" strokeWidth="1.5" strokeMiterlimit="10" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</div>
<input
type="email"
value={userProfile.email}
onChange={(e) => handleProfileUpdate('email', e.target.value)}
className="flex-1 bg-transparent text-[--Neutrals-NeutralSlate950] text-sm font-normal font-['Inter'] leading-tight outline-none"
/>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Divider */}
<div>
<svg width="100%" height="2" viewBox="0 0 2000 2" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 1H2000" stroke="var(--Neutrals-NeutralSlate200)" />
</svg>
</div>
{/* Theme Customization Section */}
<div className="w-full self-stretch p-6 flex flex-col justify-start items-start gap-6">
<div className="w-[584px] flex flex-col justify-start items-start gap-1">
<div className="self-stretch justify-start text-[--Neutrals-NeutralSlate800] text-lg font-semibold font-['Inter'] leading-7">Theme Customization</div>
<div className="self-stretch justify-start text-[--Neutrals-NeutralSlate500] text-sm font-normal font-['Inter'] leading-tight">Personalize your interface with light or dark mode and enhance your visual experience.</div>
</div>
<div className="inline-flex justify-start items-start gap-3 flex-wrap content-start">
{/* System Preference */}
<div
onClick={() => setSelectedTheme('system')}
className={`max-w-60 inline-flex flex-col justify-start items-start gap-3 cursor-pointer ${selectedTheme === 'system' ? 'opacity-100' : 'opacity-70'
}`}
>
<button className="inline-flex justify-start items-center" onClick={() => setTheme(Theme.System)}>
<img className="w-24 h-28 rounded-tl-lg rounded-bl-lg" src="/image/39a0d5e73dec8bece795a718c5800f02df8f8631.png"></img>
<img className="w-24 h-28 rounded-tr-lg rounded-br-lg" src="/image/bc07fdc9eec8a78357aaf70e9deae41d4b7a7d2d.png"></img>
</button>
<div className="self-stretch h-5 justify-start text-Text-Gray-800 text-sm font-normal font-['Inter'] leading-tight">System preference</div>
</div>
{/* Light Mode */}
<div
onClick={() => setSelectedTheme('light')}
className={`w-48 max-w-60 inline-flex flex-col justify-start items-start gap-3 cursor-pointer ${selectedTheme === 'light' ? 'opacity-100' : 'opacity-70'
}`}
>
<div className="self-stretch h-28 relative bg-[--Neutrals-NeutralSlate0] rounded-lg overflow-hidden">
<div className={`w-48 h-28 left-0 top-0 absolute bg-[--Neutrals-NeutralSlate0] rounded-[10px] outline outline-1 outline-offset-[-1px] overflow-hidden ${selectedTheme === 'light' ? 'outline-Brand-Orange' : 'outline-[--Neutrals-NeutralSlate200]'
}`}>
<button className="w-48 h-28 left-0 top-0 absolute rounded-lg" style={{ backgroundImage: 'url("/image/39a0d5e73dec8bece795a718c5800f02df8f8631.png")', backgroundSize: "cover" }} onClick={() => setTheme(Theme.Light)}></button>
</div>
</div>
<div className="self-stretch h-5 justify-start text-[--Neutrals-NeutralSlate800] text-sm font-normal font-['Inter'] leading-tight">Light Mode</div>
</div>
{/* Dark Mode */}
<div
onClick={() => setSelectedTheme('dark')}
className={`max-w-60 inline-flex flex-col justify-start items-start gap-3 cursor-pointer ${selectedTheme === 'dark' ? 'opacity-100' : 'opacity-70'
}`}
>
<div className="w-48 h-28 relative bg-[--Neutrals-NeutralSlate950] rounded-lg overflow-hidden">
<div className={`w-48 h-28 left-0 top-0 absolute bg-[--Neutrals-NeutralSlate0] rounded-[10px] outline outline-1 outline-offset-[-1px] overflow-hidden ${selectedTheme === 'dark' ? 'outline-Brand-Orange' : 'outline-[--Neutrals-NeutralSlate200]'
}`}>
<button className="w-48 h-28 left-0 top-0 absolute rounded-lg" style={{ backgroundImage: 'url("/image/bc07fdc9eec8a78357aaf70e9deae41d4b7a7d2d.png")', backgroundSize: "cover" }} onClick={() => setTheme(Theme.Dark)}></button>
</div>
</div>
<div className="self-stretch h-5 justify-start text-[--Neutrals-NeutralSlate800] text-sm font-normal font-['Inter'] leading-tight">Dark Mode</div>
</div>
</div>
</div>
{/* Another Divider */}
<div>
<svg width="2000" height="2" viewBox="0 0 2000 2" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 1H2000" stroke="var(--Neutrals-NeutralSlate200)" />
</svg>
</div>
{/* Action Buttons */}
<div className="w-[1175px] p-6 inline-flex justify-start items-center gap-2">
<div
onClick={handleReset}
className="px-3 py-2.5 bg-[--Neutrals-NeutralSlate100] rounded-[999px] flex justify-center items-center gap-1 overflow-hidden cursor-pointer hover:bg-[--Neutrals-NeutralSlate100]"
>
<div className="px-1 flex justify-center items-center">
<div className="justify-center text-[--Neutrals-NeutralSlate950] text-sm font-medium font-['Inter'] leading-tight">Reset</div>
</div>
</div>
<div
onClick={handleSaveChanges}
className="px-3 py-2.5 bg-[--Brand-Orange] rounded-[999px] outline outline-2 outline-offset-[-2px] outline-blue-400 flex justify-center items-center gap-1 overflow-hidden cursor-pointer hover:bg-[--Brand-Orange]/90"
>
<div className="px-1 flex justify-center items-center">
<div className="justify-center text-white text-sm font-medium font-['Inter'] leading-tight">Save Changes</div>
</div>
</div>
</div>
</>
)}
{/* Billing Content */}
{activeTab === 'billing' && (
<div className="flex-1 flex items-center justify-center">
<div className="text-center">
<h2 className="text-2xl font-semibold text-[--Neutrals-NeutralSlate800] mb-4">Plan & Billing</h2>
<p className="text-[--Neutrals-NeutralSlate500]">Billing management features would be implemented here.</p>
</div>
</div>
)}
</div>
</div>
);
};
export default SettingsNew;