Files
auditly/pages/SettingsNew.tsx
Ra cf565df13e feat: major UI overhaul with new components and enhanced UX
- Add comprehensive Company Wiki feature with complete state management
  - CompanyWikiManager, empty states, invite modals
- Implement new Chat system with enhanced layout and components
  - ChatLayout, ChatSidebar, MessageThread, FileUploadInput
- Create modern Login and OTP verification flows
  - LoginNew page, OTPVerification component
- Add new Employee Forms system with enhanced controller
- Introduce Figma-based design components and multiple choice inputs
- Add new font assets (NeueMontreal) and robot images for onboarding
- Enhance existing components with improved styling and functionality
- Update build configuration and dependencies
- Remove deprecated ModernLogin component
2025-08-20 04:06:49 -07:00

304 lines
23 KiB
TypeScript

import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import Sidebar from '../components/figma/Sidebar';
interface UserProfile {
fullName: string;
email: string;
profilePicture?: string;
}
type ThemeMode = 'system' | 'light' | 'dark';
const SettingsNew: React.FC = () => {
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="w-[1440px] h-[840px] p-4 bg-Neutrals-NeutralSlate200 inline-flex justify-start items-start overflow-hidden">
<div className="flex-1 self-stretch rounded-3xl shadow-[0px_0px_15px_0px_rgba(0,0,0,0.08)] flex justify-between items-start overflow-hidden">
<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-Outline-Outline-Gray-200 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-Text-Gray-800 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-Text-Gray-800 rounded-tl-lg rounded-tr-lg" />
)}
</div>
</div>
<div className="w-24 h-0.5 opacity-0 bg-Text-Gray-800 rounded-tl-lg rounded-tr-lg" />
</div>
{/* General Settings Content */}
{activeTab === 'general' && (
<>
{/* Profile Information Section */}
<div className="w-[1136px] h-72 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-Text-Gray-800 text-lg font-semibold font-['Inter'] leading-7">Profile Information</div>
<div className="self-stretch justify-start text-Text-Gray-500 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-Text-White-00 rounded-2xl outline outline-1 outline-offset-[-1px] outline-Text-Gray-200 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-Text-Gray-800 text-base font-semibold font-['Inter'] leading-normal">Profile Picture</div>
<div className="self-stretch justify-center text-Text-Gray-500 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-NeutralSlate200"
>
<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(--Text-Dark-950, #0A0D12)" 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(--Text-Gray-600, #535862)" 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(--Text-Gray-600, #535862)" 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(--Text-Gray-600, #535862)" 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="1136" height="2" viewBox="0 0 1136 2" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 1H1136" stroke="var(--Text-Gray-200, #E9EAEB)" />
</svg>
</div>
{/* Theme Customization Section */}
<div className="w-[1170px] 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-Text-Gray-800 text-lg font-semibold font-['Inter'] leading-7">Theme Customization</div>
<div className="self-stretch justify-start text-Text-Gray-500 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'
}`}
>
<div className="inline-flex justify-start items-center">
<img className="w-24 h-28 rounded-tl-lg rounded-bl-lg" src="https://via.placeholder.com/94x107/f8f9fa/6c757d?text=Light" />
<img className="w-24 h-28 rounded-tr-lg rounded-br-lg" src="https://via.placeholder.com/96x107/212529/ffffff?text=Dark" />
</div>
<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-Text-White-00 rounded-lg overflow-hidden">
<div className={`w-48 h-28 left-0 top-0 absolute bg-Text-White-00 rounded-[10px] outline outline-1 outline-offset-[-1px] overflow-hidden ${
selectedTheme === 'light' ? 'outline-Brand-Orange' : 'outline-Text-Gray-200'
}`}>
<img className="w-48 h-28 left-0 top-0 absolute rounded-lg" src="https://via.placeholder.com/190x107/f8f9fa/6c757d?text=Light+Mode" />
</div>
</div>
<div className="self-stretch h-5 justify-start text-Text-Gray-800 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-Text-White-00 rounded-lg overflow-hidden">
<div className={`w-48 h-28 left-0 top-0 absolute bg-Text-White-00 rounded-[10px] outline outline-1 outline-offset-[-1px] overflow-hidden ${
selectedTheme === 'dark' ? 'outline-Brand-Orange' : 'outline-Text-Gray-200'
}`}>
<img className="w-48 h-28 left-0 top-0 absolute rounded-lg" src="https://via.placeholder.com/190x107/212529/ffffff?text=Dark+Mode" />
</div>
</div>
<div className="self-stretch h-5 justify-start text-Text-Gray-800 text-sm font-normal font-['Inter'] leading-tight">Dark Mode</div>
</div>
</div>
</div>
{/* Another Divider */}
<div>
<svg width="1136" height="2" viewBox="0 0 1136 2" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 1H1136" stroke="var(--Text-Gray-200, #E9EAEB)" />
</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-NeutralSlate200"
>
<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-Other-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-Text-Gray-800 mb-4">Plan & Billing</h2>
<p className="text-Text-Gray-500">Billing management features would be implemented here.</p>
</div>
</div>
)}
</div>
</div>
</div>
);
};
export default SettingsNew;