website refactor

This commit is contained in:
2026-01-16 01:00:03 +01:00
parent ce7be39155
commit a98e3e3166
286 changed files with 5522 additions and 5261 deletions

View File

@@ -6,9 +6,14 @@ 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,
@@ -201,33 +206,38 @@ export default function SponsorSettingsPage() {
};
return (
<motion.div
className="max-w-4xl mx-auto py-8 px-4"
<Box
maxWidth="4xl"
mx="auto"
py={8}
px={4}
as={motion.div}
// @ts-ignore
variants={containerVariants}
initial="hidden"
animate="visible"
>
{/* Header */}
<motion.div variants={itemVariants}>
<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} />}
/>
</motion.div>
</Box>
{/* Company Profile */}
<motion.div variants={itemVariants}>
<Box as={motion.div} variants={itemVariants}>
<Card className="mb-6 overflow-hidden">
<SectionHeader
icon={Building2}
title="Company Profile"
description="Your public-facing company information"
/>
<div className="p-6 space-y-6">
<Box p={6} className="space-y-6">
{/* Company Basic Info */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Box display="grid" gridCols={{ base: 1, md: 2 }} gap={6}>
<FormField label="Company Name" icon={Building2} required>
<Input
type="text"
@@ -238,24 +248,32 @@ export default function SponsorSettingsPage() {
</FormField>
<FormField label="Industry">
<select
<Box as="select"
value={profile.industry}
onChange={(e) => setProfile({ ...profile, industry: e.target.value })}
className="w-full px-3 py-2 bg-iron-gray border border-charcoal-outline rounded-lg text-white focus:outline-none focus:border-primary-blue"
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>
))}
</select>
</Box>
</FormField>
</div>
</Box>
{/* Contact Information */}
<div className="pt-4 border-t border-charcoal-outline/50">
<h3 className="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-4">
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
<Heading level={3} fontSize="sm" weight="semibold" color="text-gray-400" mb={4}>
Contact Information
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
</Heading>
<Box display="grid" gridCols={{ base: 1, md: 2 }} gap={6}>
<FormField label="Contact Name" icon={User} required>
<Input
type="text"
@@ -291,16 +309,16 @@ export default function SponsorSettingsPage() {
placeholder="https://company.com"
/>
</FormField>
</div>
</div>
</Box>
</Box>
{/* Address */}
<div className="pt-4 border-t border-charcoal-outline/50">
<h3 className="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-4">
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
<Heading level={3} fontSize="sm" weight="semibold" color="text-gray-400" mb={4}>
Business Address
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="md:col-span-2">
</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"
@@ -312,7 +330,7 @@ export default function SponsorSettingsPage() {
placeholder="123 Main Street"
/>
</FormField>
</div>
</Box>
<FormField label="City">
<Input
@@ -358,31 +376,39 @@ export default function SponsorSettingsPage() {
placeholder="XX12-3456789"
/>
</FormField>
</div>
</div>
</Box>
</Box>
{/* Description */}
<div className="pt-4 border-t border-charcoal-outline/50">
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
<FormField label="Company Description">
<textarea
<Box as="textarea"
value={profile.description}
onChange={(e) => setProfile({ ...profile, description: e.target.value })}
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}
className="w-full px-4 py-3 bg-iron-gray border border-charcoal-outline rounded-lg text-white placeholder-gray-500 focus:outline-none focus:border-primary-blue resize-none"
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"
/>
<p className="text-xs text-gray-500 mt-1">
<Text size="xs" color="text-gray-500" block mt={1}>
This description appears on your public sponsor profile.
</p>
</Text>
</FormField>
</div>
</Box>
{/* Social Links */}
<div className="pt-4 border-t border-charcoal-outline/50">
<h3 className="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-4">
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
<Heading level={3} fontSize="sm" weight="semibold" color="text-gray-400" mb={4}>
Social Media
</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
</Heading>
<Box display="grid" gridCols={{ base: 1, md: 3 }} gap={6}>
<FormField label="Twitter / X" icon={LinkIcon}>
<Input
type="text"
@@ -418,49 +444,49 @@ export default function SponsorSettingsPage() {
placeholder="@username"
/>
</FormField>
</div>
</div>
</Box>
</Box>
{/* Logo Upload */}
<div className="pt-4 border-t border-charcoal-outline/50">
<Box pt={4} borderTop borderColor="border-charcoal-outline/50">
<FormField label="Company Logo" icon={ImageIcon}>
<div className="flex items-start gap-6">
<div className="w-24 h-24 rounded-xl bg-gradient-to-br from-iron-gray to-deep-graphite border-2 border-dashed border-charcoal-outline flex items-center justify-center overflow-hidden">
<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 ? (
<img src={profile.logoUrl} alt="Company logo" className="w-full h-full object-cover" />
<Image src={profile.logoUrl} alt="Company logo" width={96} height={96} objectFit="cover" />
) : (
<Building2 className="w-10 h-10 text-gray-600" />
)}
</div>
<div className="flex-1">
<div className="flex items-center gap-3">
<label className="cursor-pointer">
</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"
/>
<div className="px-4 py-2 rounded-lg bg-iron-gray border border-charcoal-outline text-gray-300 hover:bg-charcoal-outline transition-colors flex items-center gap-2">
<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" />
Upload Logo
</div>
</label>
<Text>Upload Logo</Text>
</Box>
</Text>
{profile.logoUrl && (
<Button variant="secondary" className="text-sm text-gray-400">
Remove
</Button>
)}
</div>
<p className="text-xs text-gray-500 mt-2">
</Stack>
<Text size="xs" color="text-gray-500" block mt={2}>
PNG, JPEG, or SVG. Max 2MB. Recommended size: 400x400px.
</p>
</div>
</div>
</Text>
</Box>
</Stack>
</FormField>
</div>
</Box>
{/* Save Button */}
<div className="pt-6 border-t border-charcoal-outline flex items-center justify-end gap-4">
<Box pt={6} borderTop borderColor="border-charcoal-outline" display="flex" alignItems="center" justifyContent="end" gap={4}>
<Button
variant="primary"
onClick={handleSaveProfile}
@@ -468,24 +494,24 @@ export default function SponsorSettingsPage() {
className="min-w-[160px]"
>
{saving ? (
<span className="flex items-center gap-2">
<span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
Saving...
</span>
<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>
) : (
<span className="flex items-center gap-2">
<Stack direction="row" align="center" gap={2}>
<Save className="w-4 h-4" />
Save Profile
</span>
<Text>Save Profile</Text>
</Stack>
)}
</Button>
</div>
</div>
</Box>
</Box>
</Card>
</motion.div>
</Box>
{/* Notification Preferences */}
<motion.div variants={itemVariants}>
<Box as={motion.div} variants={itemVariants}>
<Card className="mb-6 overflow-hidden">
<SectionHeader
icon={Bell}
@@ -493,8 +519,8 @@ export default function SponsorSettingsPage() {
description="Control which emails you receive from GridPilot"
color="text-warning-amber"
/>
<div className="p-6">
<div className="space-y-1">
<Box p={6}>
<Box className="space-y-1">
<Toggle
checked={notifications.emailNewSponsorships}
onChange={(checked) => setNotifications({ ...notifications, emailNewSponsorships: checked })}
@@ -531,13 +557,13 @@ export default function SponsorSettingsPage() {
label="Contract Expiry Reminders"
description="Receive reminders before your sponsorship contracts expire"
/>
</div>
</div>
</Box>
</Box>
</Card>
</motion.div>
</Box>
{/* Privacy & Visibility */}
<motion.div variants={itemVariants}>
<Box as={motion.div} variants={itemVariants}>
<Card className="mb-6 overflow-hidden">
<SectionHeader
icon={Eye}
@@ -545,8 +571,8 @@ export default function SponsorSettingsPage() {
description="Control how your profile appears to others"
color="text-performance-green"
/>
<div className="p-6">
<div className="space-y-1">
<Box p={6}>
<Box className="space-y-1">
<Toggle
checked={privacy.publicProfile}
onChange={(checked) => setPrivacy({ ...privacy, publicProfile: checked })}
@@ -571,13 +597,13 @@ export default function SponsorSettingsPage() {
label="Allow Direct Contact"
description="Enable leagues and teams to send you sponsorship proposals"
/>
</div>
</div>
</Box>
</Box>
</Card>
</motion.div>
</Box>
{/* Security */}
<motion.div variants={itemVariants}>
<Box as={motion.div} variants={itemVariants}>
<Card className="mb-6 overflow-hidden">
<SectionHeader
icon={Shield}
@@ -585,80 +611,77 @@ export default function SponsorSettingsPage() {
description="Protect your sponsor account"
color="text-primary-blue"
/>
<div className="p-6 space-y-4">
<div className="flex items-center justify-between py-3 border-b border-charcoal-outline/50">
<div className="flex items-center gap-4">
<div className="p-2 rounded-lg bg-iron-gray">
<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" />
</div>
<div>
<p className="text-gray-200 font-medium">Password</p>
<p className="text-sm text-gray-500">Last changed 3 months ago</p>
</div>
</div>
</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>
</div>
</Box>
<div className="flex items-center justify-between py-3 border-b border-charcoal-outline/50">
<div className="flex items-center gap-4">
<div className="p-2 rounded-lg bg-iron-gray">
<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" />
</div>
<div>
<p className="text-gray-200 font-medium">Two-Factor Authentication</p>
<p className="text-sm text-gray-500">Add an extra layer of security to your account</p>
</div>
</div>
</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>
</div>
</Box>
<div className="flex items-center justify-between py-3">
<div className="flex items-center gap-4">
<div className="p-2 rounded-lg bg-iron-gray">
<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" />
</div>
<div>
<p className="text-gray-200 font-medium">Active Sessions</p>
<p className="text-sm text-gray-500">Manage devices where you're logged in</p>
</div>
</div>
</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&apos;re logged in</Text>
</Box>
</Stack>
<Button variant="secondary">
View Sessions
</Button>
</div>
</div>
</Box>
</Box>
</Card>
</motion.div>
</Box>
{/* Danger Zone */}
<motion.div variants={itemVariants}>
<Box as={motion.div} variants={itemVariants}>
<Card className="border-racing-red/30 overflow-hidden">
<div className="p-5 border-b border-racing-red/30 bg-gradient-to-r from-racing-red/10 to-transparent">
<h2 className="text-lg font-semibold text-racing-red flex items-center gap-3">
<div className="p-2 rounded-lg bg-racing-red/10">
<AlertCircle className="w-5 h-5 text-racing-red" />
</div>
<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
</h2>
</div>
<div className="p-6">
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<div className="p-2 rounded-lg bg-racing-red/10">
</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" />
</div>
<div>
<p className="text-gray-200 font-medium">Delete Sponsor Account</p>
<p className="text-sm text-gray-500">
</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.
</p>
</div>
</div>
</Text>
</Box>
</Stack>
<Button
variant="secondary"
onClick={handleDeleteAccount}
@@ -666,10 +689,10 @@ export default function SponsorSettingsPage() {
>
Delete Account
</Button>
</div>
</div>
</Box>
</Box>
</Card>
</motion.div>
</motion.div>
</Box>
</Box>
);
}