website refactor
This commit is contained in:
@@ -1,92 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
import { Card } from '@/ui/Card';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Input } from '@/ui/Input';
|
||||
import { Toggle } from '@/ui/Toggle';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { SectionHeader } from '@/ui/SectionHeader';
|
||||
import { FormField } from '@/ui/FormField';
|
||||
import { PageHeader } from '@/ui/PageHeader';
|
||||
import { Image } from '@/ui/Image';
|
||||
import {
|
||||
Settings,
|
||||
Building2,
|
||||
Mail,
|
||||
Globe,
|
||||
Upload,
|
||||
Save,
|
||||
Bell,
|
||||
Shield,
|
||||
Eye,
|
||||
Trash2,
|
||||
CheckCircle,
|
||||
User,
|
||||
Phone,
|
||||
MapPin,
|
||||
FileText,
|
||||
Link as LinkIcon,
|
||||
Image as ImageIcon,
|
||||
Lock,
|
||||
Key,
|
||||
Smartphone,
|
||||
AlertCircle
|
||||
} from 'lucide-react';
|
||||
import { SponsorSettingsTemplate } from '@/templates/SponsorSettingsTemplate';
|
||||
import { logoutAction } from '@/app/actions/logoutAction';
|
||||
|
||||
// ============================================================================
|
||||
// Types
|
||||
// ============================================================================
|
||||
|
||||
interface SponsorProfile {
|
||||
companyName: string;
|
||||
contactName: string;
|
||||
contactEmail: string;
|
||||
contactPhone: string;
|
||||
website: string;
|
||||
description: string;
|
||||
logoUrl: string | null;
|
||||
industry: string;
|
||||
address: {
|
||||
street: string;
|
||||
city: string;
|
||||
country: string;
|
||||
postalCode: string;
|
||||
};
|
||||
taxId: string;
|
||||
socialLinks: {
|
||||
twitter: string;
|
||||
linkedin: string;
|
||||
instagram: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface NotificationSettings {
|
||||
emailNewSponsorships: boolean;
|
||||
emailWeeklyReport: boolean;
|
||||
emailRaceAlerts: boolean;
|
||||
emailPaymentAlerts: boolean;
|
||||
emailNewOpportunities: boolean;
|
||||
emailContractExpiry: boolean;
|
||||
}
|
||||
|
||||
interface PrivacySettings {
|
||||
publicProfile: boolean;
|
||||
showStats: boolean;
|
||||
showActiveSponsorships: boolean;
|
||||
allowDirectContact: boolean;
|
||||
}
|
||||
import { ConfirmDialog } from '@/components/shared/ux/ConfirmDialog';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
// ============================================================================
|
||||
// Mock Data
|
||||
// ============================================================================
|
||||
|
||||
const MOCK_PROFILE: SponsorProfile = {
|
||||
const MOCK_PROFILE = {
|
||||
companyName: 'Acme Racing Co.',
|
||||
contactName: 'John Smith',
|
||||
contactEmail: 'sponsor@acme-racing.com',
|
||||
@@ -109,7 +33,7 @@ const MOCK_PROFILE: SponsorProfile = {
|
||||
},
|
||||
};
|
||||
|
||||
const MOCK_NOTIFICATIONS: NotificationSettings = {
|
||||
const MOCK_NOTIFICATIONS = {
|
||||
emailNewSponsorships: true,
|
||||
emailWeeklyReport: true,
|
||||
emailRaceAlerts: false,
|
||||
@@ -118,581 +42,71 @@ const MOCK_NOTIFICATIONS: NotificationSettings = {
|
||||
emailContractExpiry: true,
|
||||
};
|
||||
|
||||
const MOCK_PRIVACY: PrivacySettings = {
|
||||
const MOCK_PRIVACY = {
|
||||
publicProfile: true,
|
||||
showStats: false,
|
||||
showActiveSponsorships: true,
|
||||
allowDirectContact: true,
|
||||
};
|
||||
|
||||
const INDUSTRY_OPTIONS = [
|
||||
'Racing Equipment',
|
||||
'Automotive',
|
||||
'Technology',
|
||||
'Gaming & Esports',
|
||||
'Energy Drinks',
|
||||
'Apparel',
|
||||
'Financial Services',
|
||||
'Other',
|
||||
];
|
||||
|
||||
// ============================================================================
|
||||
// Components
|
||||
// ============================================================================
|
||||
|
||||
function SavedIndicator({ visible }: { visible: boolean }) {
|
||||
const shouldReduceMotion = useReducedMotion();
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 20 }}
|
||||
animate={{ opacity: visible ? 1 : 0, x: visible ? 0 : 20 }}
|
||||
transition={{ duration: shouldReduceMotion ? 0 : 0.2 }}
|
||||
className="flex items-center gap-2 text-performance-green"
|
||||
>
|
||||
<CheckCircle className="w-4 h-4" />
|
||||
<span className="text-sm font-medium">Changes saved</span>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Main Component
|
||||
// ============================================================================
|
||||
|
||||
export default function SponsorSettingsPage() {
|
||||
const shouldReduceMotion = useReducedMotion();
|
||||
const router = useRouter();
|
||||
const [profile, setProfile] = useState(MOCK_PROFILE);
|
||||
const [notifications, setNotifications] = useState(MOCK_NOTIFICATIONS);
|
||||
const [privacy, setPrivacy] = useState(MOCK_PRIVACY);
|
||||
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [saved, setSaved] = useState(false);
|
||||
|
||||
const handleSaveProfile = async () => {
|
||||
setSaving(true);
|
||||
await new Promise(resolve => setTimeout(resolve, 800));
|
||||
console.log('Profile saved:', profile);
|
||||
setSaving(false);
|
||||
setSaved(true);
|
||||
setTimeout(() => setSaved(false), 3000);
|
||||
};
|
||||
|
||||
const handleDeleteAccount = async () => {
|
||||
if (confirm('Are you sure you want to delete your sponsor account? This action cannot be undone. All sponsorship data will be permanently removed.')) {
|
||||
// Call the logout action and handle result
|
||||
const result = await logoutAction();
|
||||
if (result.isErr()) {
|
||||
console.error('Logout failed:', result.getError());
|
||||
// Could show error toast here
|
||||
return;
|
||||
}
|
||||
// Redirect to login after successful logout
|
||||
window.location.href = '/auth/login';
|
||||
setIsDeleting(true);
|
||||
const result = await logoutAction();
|
||||
if (result.isErr()) {
|
||||
console.error('Logout failed:', result.getError());
|
||||
setIsDeleting(false);
|
||||
return;
|
||||
}
|
||||
router.push('/auth/login');
|
||||
};
|
||||
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: shouldReduceMotion ? 0 : 0.1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const itemVariants = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: { opacity: 1, y: 0 },
|
||||
const viewData = {
|
||||
profile: MOCK_PROFILE,
|
||||
notifications: MOCK_NOTIFICATIONS,
|
||||
privacy: MOCK_PRIVACY,
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
maxWidth="4xl"
|
||||
mx="auto"
|
||||
py={8}
|
||||
px={4}
|
||||
as={motion.div}
|
||||
// @ts-ignore
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
>
|
||||
{/* Header */}
|
||||
<Box as={motion.div} variants={itemVariants}>
|
||||
<PageHeader
|
||||
icon={Settings}
|
||||
title="Sponsor Settings"
|
||||
description="Manage your company profile, notifications, and security preferences"
|
||||
action={<SavedIndicator visible={saved} />}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Company Profile */}
|
||||
<Box as={motion.div} variants={itemVariants}>
|
||||
<Card className="mb-6 overflow-hidden">
|
||||
<SectionHeader
|
||||
icon={Building2}
|
||||
title="Company Profile"
|
||||
description="Your public-facing company information"
|
||||
/>
|
||||
<Box p={6} className="space-y-6">
|
||||
{/* Company Basic Info */}
|
||||
<Box display="grid" gridCols={{ base: 1, md: 2 }} gap={6}>
|
||||
<FormField label="Company Name" icon={Building2} required>
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.companyName}
|
||||
onChange={(e) => setProfile({ ...profile, companyName: e.target.value })}
|
||||
placeholder="Your company name"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Industry">
|
||||
<Box as="select"
|
||||
value={profile.industry}
|
||||
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => setProfile({ ...profile, industry: e.target.value })}
|
||||
w="full"
|
||||
px={3}
|
||||
py={2}
|
||||
bg="bg-iron-gray"
|
||||
border
|
||||
borderColor="border-charcoal-outline"
|
||||
rounded="lg"
|
||||
color="text-white"
|
||||
className="focus:outline-none focus:border-primary-blue"
|
||||
>
|
||||
{INDUSTRY_OPTIONS.map(industry => (
|
||||
<option key={industry} value={industry}>{industry}</option>
|
||||
))}
|
||||
</Box>
|
||||
</FormField>
|
||||
</Box>
|
||||
|
||||
{/* Contact Information */}
|
||||
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
|
||||
<Heading level={3} fontSize="sm" weight="semibold" color="text-gray-400" mb={4}>
|
||||
Contact Information
|
||||
</Heading>
|
||||
<Box display="grid" gridCols={{ base: 1, md: 2 }} gap={6}>
|
||||
<FormField label="Contact Name" icon={User} required>
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.contactName}
|
||||
onChange={(e) => setProfile({ ...profile, contactName: e.target.value })}
|
||||
placeholder="Full name"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Contact Email" icon={Mail} required>
|
||||
<Input
|
||||
type="email"
|
||||
value={profile.contactEmail}
|
||||
onChange={(e) => setProfile({ ...profile, contactEmail: e.target.value })}
|
||||
placeholder="sponsor@company.com"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Phone Number" icon={Phone}>
|
||||
<Input
|
||||
type="tel"
|
||||
value={profile.contactPhone}
|
||||
onChange={(e) => setProfile({ ...profile, contactPhone: e.target.value })}
|
||||
placeholder="+1 (555) 123-4567"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Website" icon={Globe}>
|
||||
<Input
|
||||
type="url"
|
||||
value={profile.website}
|
||||
onChange={(e) => setProfile({ ...profile, website: e.target.value })}
|
||||
placeholder="https://company.com"
|
||||
/>
|
||||
</FormField>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Address */}
|
||||
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
|
||||
<Heading level={3} fontSize="sm" weight="semibold" color="text-gray-400" mb={4}>
|
||||
Business Address
|
||||
</Heading>
|
||||
<Box display="grid" gridCols={{ base: 1, md: 2 }} gap={6}>
|
||||
<Box colSpan={{ base: 1, md: 2 }}>
|
||||
<FormField label="Street Address" icon={MapPin}>
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.address.street}
|
||||
onChange={(e) => setProfile({
|
||||
...profile,
|
||||
address: { ...profile.address, street: e.target.value }
|
||||
})}
|
||||
placeholder="123 Main Street"
|
||||
/>
|
||||
</FormField>
|
||||
</Box>
|
||||
|
||||
<FormField label="City">
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.address.city}
|
||||
onChange={(e) => setProfile({
|
||||
...profile,
|
||||
address: { ...profile.address, city: e.target.value }
|
||||
})}
|
||||
placeholder="City"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Postal Code">
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.address.postalCode}
|
||||
onChange={(e) => setProfile({
|
||||
...profile,
|
||||
address: { ...profile.address, postalCode: e.target.value }
|
||||
})}
|
||||
placeholder="12345"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Country">
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.address.country}
|
||||
onChange={(e) => setProfile({
|
||||
...profile,
|
||||
address: { ...profile.address, country: e.target.value }
|
||||
})}
|
||||
placeholder="Country"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Tax ID / VAT Number" icon={FileText}>
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.taxId}
|
||||
onChange={(e) => setProfile({ ...profile, taxId: e.target.value })}
|
||||
placeholder="XX12-3456789"
|
||||
/>
|
||||
</FormField>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Description */}
|
||||
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
|
||||
<FormField label="Company Description">
|
||||
<Box as="textarea"
|
||||
value={profile.description}
|
||||
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setProfile({ ...profile, description: e.target.value })}
|
||||
placeholder="Tell potential sponsorship partners about your company, products, and what you're looking for in sponsorship opportunities..."
|
||||
rows={4}
|
||||
w="full"
|
||||
px={4}
|
||||
py={3}
|
||||
bg="bg-iron-gray"
|
||||
border
|
||||
borderColor="border-charcoal-outline"
|
||||
rounded="lg"
|
||||
color="text-white"
|
||||
className="placeholder-gray-500 focus:outline-none focus:border-primary-blue resize-none"
|
||||
/>
|
||||
<Text size="xs" color="text-gray-500" block mt={1}>
|
||||
This description appears on your public sponsor profile.
|
||||
</Text>
|
||||
</FormField>
|
||||
</Box>
|
||||
|
||||
{/* Social Links */}
|
||||
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
|
||||
<Heading level={3} fontSize="sm" weight="semibold" color="text-gray-400" mb={4}>
|
||||
Social Media
|
||||
</Heading>
|
||||
<Box display="grid" gridCols={{ base: 1, md: 3 }} gap={6}>
|
||||
<FormField label="Twitter / X" icon={LinkIcon}>
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.socialLinks.twitter}
|
||||
onChange={(e) => setProfile({
|
||||
...profile,
|
||||
socialLinks: { ...profile.socialLinks, twitter: e.target.value }
|
||||
})}
|
||||
placeholder="@username"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="LinkedIn" icon={LinkIcon}>
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.socialLinks.linkedin}
|
||||
onChange={(e) => setProfile({
|
||||
...profile,
|
||||
socialLinks: { ...profile.socialLinks, linkedin: e.target.value }
|
||||
})}
|
||||
placeholder="company-name"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Instagram" icon={LinkIcon}>
|
||||
<Input
|
||||
type="text"
|
||||
value={profile.socialLinks.instagram}
|
||||
onChange={(e) => setProfile({
|
||||
...profile,
|
||||
socialLinks: { ...profile.socialLinks, instagram: e.target.value }
|
||||
})}
|
||||
placeholder="@username"
|
||||
/>
|
||||
</FormField>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Logo Upload */}
|
||||
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
|
||||
<FormField label="Company Logo" icon={ImageIcon}>
|
||||
<Stack direction="row" align="start" gap={6}>
|
||||
<Box w="24" h="24" rounded="xl" bg="bg-gradient-to-br from-iron-gray to-deep-graphite" border borderColor="border-charcoal-outline" borderStyle="dashed" display="flex" alignItems="center" justifyContent="center" overflow="hidden">
|
||||
{profile.logoUrl ? (
|
||||
<Image src={profile.logoUrl} alt="Company logo" width={96} height={96} objectFit="cover" />
|
||||
) : (
|
||||
<Building2 className="w-10 h-10 text-gray-600" />
|
||||
)}
|
||||
</Box>
|
||||
<Box flexGrow={1}>
|
||||
<Stack direction="row" align="center" gap={3}>
|
||||
<Text as="label" cursor="pointer">
|
||||
<input
|
||||
type="file"
|
||||
accept="image/png,image/jpeg,image/svg+xml"
|
||||
className="hidden"
|
||||
/>
|
||||
<Box px={4} py={2} rounded="lg" bg="bg-iron-gray" border borderColor="border-charcoal-outline" color="text-gray-300" transition className="hover:bg-charcoal-outline" display="flex" alignItems="center" gap={2}>
|
||||
<Upload className="w-4 h-4" />
|
||||
<Text>Upload Logo</Text>
|
||||
</Box>
|
||||
</Text>
|
||||
{profile.logoUrl && (
|
||||
<Button variant="secondary" className="text-sm text-gray-400">
|
||||
Remove
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
<Text size="xs" color="text-gray-500" block mt={2}>
|
||||
PNG, JPEG, or SVG. Max 2MB. Recommended size: 400x400px.
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</FormField>
|
||||
</Box>
|
||||
|
||||
{/* Save Button */}
|
||||
<Box pt={6} borderTop borderColor="border-charcoal-outline" display="flex" alignItems="center" justifyContent="end" gap={4}>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleSaveProfile}
|
||||
disabled={saving}
|
||||
className="min-w-[160px]"
|
||||
>
|
||||
{saving ? (
|
||||
<Stack direction="row" align="center" gap={2}>
|
||||
<Box w="4" h="4" border borderColor="border-white/30" borderTopColor="border-t-white" rounded="full" animate="spin" />
|
||||
<Text>Saving...</Text>
|
||||
</Stack>
|
||||
) : (
|
||||
<Stack direction="row" align="center" gap={2}>
|
||||
<Save className="w-4 h-4" />
|
||||
<Text>Save Profile</Text>
|
||||
</Stack>
|
||||
)}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Card>
|
||||
</Box>
|
||||
|
||||
{/* Notification Preferences */}
|
||||
<Box as={motion.div} variants={itemVariants}>
|
||||
<Card className="mb-6 overflow-hidden">
|
||||
<SectionHeader
|
||||
icon={Bell}
|
||||
title="Email Notifications"
|
||||
description="Control which emails you receive from GridPilot"
|
||||
color="text-warning-amber"
|
||||
/>
|
||||
<Box p={6}>
|
||||
<Box className="space-y-1">
|
||||
<Toggle
|
||||
checked={notifications.emailNewSponsorships}
|
||||
onChange={(checked) => setNotifications({ ...notifications, emailNewSponsorships: checked })}
|
||||
label="Sponsorship Approvals"
|
||||
description="Receive confirmation when your sponsorship requests are approved"
|
||||
/>
|
||||
<Toggle
|
||||
checked={notifications.emailWeeklyReport}
|
||||
onChange={(checked) => setNotifications({ ...notifications, emailWeeklyReport: checked })}
|
||||
label="Weekly Analytics Report"
|
||||
description="Get a weekly summary of your sponsorship performance"
|
||||
/>
|
||||
<Toggle
|
||||
checked={notifications.emailRaceAlerts}
|
||||
onChange={(checked) => setNotifications({ ...notifications, emailRaceAlerts: checked })}
|
||||
label="Race Day Alerts"
|
||||
description="Be notified when sponsored leagues have upcoming races"
|
||||
/>
|
||||
<Toggle
|
||||
checked={notifications.emailPaymentAlerts}
|
||||
onChange={(checked) => setNotifications({ ...notifications, emailPaymentAlerts: checked })}
|
||||
label="Payment & Invoice Notifications"
|
||||
description="Receive invoices and payment confirmations"
|
||||
/>
|
||||
<Toggle
|
||||
checked={notifications.emailNewOpportunities}
|
||||
onChange={(checked) => setNotifications({ ...notifications, emailNewOpportunities: checked })}
|
||||
label="New Sponsorship Opportunities"
|
||||
description="Get notified about new leagues and drivers seeking sponsors"
|
||||
/>
|
||||
<Toggle
|
||||
checked={notifications.emailContractExpiry}
|
||||
onChange={(checked) => setNotifications({ ...notifications, emailContractExpiry: checked })}
|
||||
label="Contract Expiry Reminders"
|
||||
description="Receive reminders before your sponsorship contracts expire"
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Card>
|
||||
</Box>
|
||||
|
||||
{/* Privacy & Visibility */}
|
||||
<Box as={motion.div} variants={itemVariants}>
|
||||
<Card className="mb-6 overflow-hidden">
|
||||
<SectionHeader
|
||||
icon={Eye}
|
||||
title="Privacy & Visibility"
|
||||
description="Control how your profile appears to others"
|
||||
color="text-performance-green"
|
||||
/>
|
||||
<Box p={6}>
|
||||
<Box className="space-y-1">
|
||||
<Toggle
|
||||
checked={privacy.publicProfile}
|
||||
onChange={(checked) => setPrivacy({ ...privacy, publicProfile: checked })}
|
||||
label="Public Profile"
|
||||
description="Allow leagues, teams, and drivers to view your sponsor profile"
|
||||
/>
|
||||
<Toggle
|
||||
checked={privacy.showStats}
|
||||
onChange={(checked) => setPrivacy({ ...privacy, showStats: checked })}
|
||||
label="Show Sponsorship Statistics"
|
||||
description="Display your total sponsorships and investment amounts"
|
||||
/>
|
||||
<Toggle
|
||||
checked={privacy.showActiveSponsorships}
|
||||
onChange={(checked) => setPrivacy({ ...privacy, showActiveSponsorships: checked })}
|
||||
label="Show Active Sponsorships"
|
||||
description="Let others see which leagues and teams you currently sponsor"
|
||||
/>
|
||||
<Toggle
|
||||
checked={privacy.allowDirectContact}
|
||||
onChange={(checked) => setPrivacy({ ...privacy, allowDirectContact: checked })}
|
||||
label="Allow Direct Contact"
|
||||
description="Enable leagues and teams to send you sponsorship proposals"
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Card>
|
||||
</Box>
|
||||
|
||||
{/* Security */}
|
||||
<Box as={motion.div} variants={itemVariants}>
|
||||
<Card className="mb-6 overflow-hidden">
|
||||
<SectionHeader
|
||||
icon={Shield}
|
||||
title="Account Security"
|
||||
description="Protect your sponsor account"
|
||||
color="text-primary-blue"
|
||||
/>
|
||||
<Box p={6} className="space-y-4">
|
||||
<Box display="flex" alignItems="center" justifyContent="between" py={3} borderBottom borderColor="border-charcoal-outline/50">
|
||||
<Stack direction="row" align="center" gap={4}>
|
||||
<Box p={2} rounded="lg" bg="bg-iron-gray">
|
||||
<Key className="w-5 h-5 text-gray-400" />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text color="text-gray-200" weight="medium" block>Password</Text>
|
||||
<Text size="sm" color="text-gray-500" block>Last changed 3 months ago</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Button variant="secondary">
|
||||
Change Password
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<Box display="flex" alignItems="center" justifyContent="between" py={3} borderBottom borderColor="border-charcoal-outline/50">
|
||||
<Stack direction="row" align="center" gap={4}>
|
||||
<Box p={2} rounded="lg" bg="bg-iron-gray">
|
||||
<Smartphone className="w-5 h-5 text-gray-400" />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text color="text-gray-200" weight="medium" block>Two-Factor Authentication</Text>
|
||||
<Text size="sm" color="text-gray-500" block>Add an extra layer of security to your account</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Button variant="secondary">
|
||||
Enable 2FA
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<Box display="flex" alignItems="center" justifyContent="between" py={3}>
|
||||
<Stack direction="row" align="center" gap={4}>
|
||||
<Box p={2} rounded="lg" bg="bg-iron-gray">
|
||||
<Lock className="w-5 h-5 text-gray-400" />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text color="text-gray-200" weight="medium" block>Active Sessions</Text>
|
||||
<Text size="sm" color="text-gray-500" block>Manage devices where you're logged in</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Button variant="secondary">
|
||||
View Sessions
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Card>
|
||||
</Box>
|
||||
|
||||
{/* Danger Zone */}
|
||||
<Box as={motion.div} variants={itemVariants}>
|
||||
<Card className="border-racing-red/30 overflow-hidden">
|
||||
<Box p={5} borderBottom borderColor="border-racing-red/30" bg="bg-gradient-to-r from-racing-red/10 to-transparent">
|
||||
<Heading level={2} fontSize="lg" weight="semibold" color="text-racing-red" icon={<Box p={2} rounded="lg" bg="bg-racing-red/10"><AlertCircle className="w-5 h-5 text-racing-red" /></Box>}>
|
||||
Danger Zone
|
||||
</Heading>
|
||||
</Box>
|
||||
<Box p={6}>
|
||||
<Box display="flex" alignItems="center" justifyContent="between">
|
||||
<Stack direction="row" align="center" gap={4}>
|
||||
<Box p={2} rounded="lg" bg="bg-racing-red/10">
|
||||
<Trash2 className="w-5 h-5 text-racing-red" />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text color="text-gray-200" weight="medium" block>Delete Sponsor Account</Text>
|
||||
<Text size="sm" color="text-gray-500" block>
|
||||
Permanently delete your account and all associated sponsorship data.
|
||||
This action cannot be undone.
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={handleDeleteAccount}
|
||||
className="text-racing-red border-racing-red/30 hover:bg-racing-red/10"
|
||||
>
|
||||
Delete Account
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Card>
|
||||
</Box>
|
||||
</Box>
|
||||
<>
|
||||
<SponsorSettingsTemplate
|
||||
viewData={viewData}
|
||||
profile={profile}
|
||||
setProfile={setProfile as any}
|
||||
notifications={notifications}
|
||||
setNotifications={setNotifications as any}
|
||||
onSaveProfile={handleSaveProfile}
|
||||
onDeleteAccount={() => setIsDeleteDialogOpen(true)}
|
||||
saving={saving}
|
||||
saved={saved}
|
||||
/>
|
||||
<ConfirmDialog
|
||||
isOpen={isDeleteDialogOpen}
|
||||
onClose={() => setIsDeleteDialogOpen(false)}
|
||||
onConfirm={handleDeleteAccount}
|
||||
title="Delete Sponsor Account"
|
||||
description="Are you sure you want to delete your sponsor account? This action cannot be undone. All sponsorship data, contracts, and history will be permanently removed."
|
||||
confirmLabel="Delete Account"
|
||||
variant="danger"
|
||||
isLoading={isDeleting}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user