11import { User , Link2 , Shield , Image , Star } from 'lucide-react' ;
22import type { Settings } from '../../types/settings' ;
3-
4- // DESIGN TOKENS (Shared across all 6 components)
5- const TOKENS = {
6- section : "bg-zinc-800/40 border border-zinc-700/30 rounded-lg p-5 transition-all duration-200" ,
7- iconBox : "p-2.5 rounded-lg flex-shrink-0 flex items-center justify-center" ,
8- label : "text-zinc-100 font-medium text-sm sm:text-base" ,
9- description : "text-zinc-400 text-xs sm:text-sm mt-0.5 leading-relaxed" ,
10- toggle : {
11- base : "relative w-11 h-6 rounded-full transition-all duration-200 outline-none" ,
12- dot : "absolute top-1 left-1 bg-white w-4 h-4 rounded-full transition-transform duration-200" ,
13- }
14- } ;
3+ import Toggle from './Toggle' ;
4+ import { S } from './settingsTokens' ;
155
166interface PrivacySettingsProps {
177 settings : Settings | null ;
188 onChange : ( updatedSettings : Settings ) => void ;
199}
2010
21- export default function PrivacySettings ( { settings, onChange } : PrivacySettingsProps ) {
22- if ( ! settings ) return null ;
23-
24- const toggleSetting = ( key : keyof Settings ) => {
25- onChange ( {
26- ...settings ,
27- [ key ] : ! settings [ key ] ,
28- } ) ;
29- } ;
11+ interface PrivacyRowProps {
12+ icon : React . ReactNode ;
13+ title : string ;
14+ description : string ;
15+ checked : boolean ;
16+ onChange : ( checked : boolean ) => void ;
17+ }
3018
31- const SETTINGS_MAP = [
32- {
33- id : 'displayStatsOnProfile' ,
34- label : 'Display Statistics' ,
35- desc : 'Show sessions created, time controlling, and total flights.' ,
36- icon : User ,
37- color : 'blue'
38- } ,
39- {
40- id : 'displayControllerRatingOnProfile' ,
41- label : 'Controller Rating' ,
42- desc : 'Show your average controller rating and total feedback.' ,
43- icon : Star ,
44- color : 'yellow'
45- } ,
46- {
47- id : 'displayLinkedAccountsOnProfile' ,
48- label : 'Linked Accounts' ,
49- desc : 'Visibility for Roblox and VATSIM integrations.' ,
50- icon : Link2 ,
51- color : 'purple'
52- } ,
53- {
54- id : 'displayBackgroundOnProfile' ,
55- label : 'Profile Background' ,
56- desc : 'Show your selected background image in your profile header.' ,
57- icon : Image ,
58- color : 'emerald'
59- } ,
60- {
61- id : 'hideFromLeaderboard' ,
62- label : 'Leaderboard Privacy' ,
63- desc : 'Opt out of appearing in the homepage rankings.' ,
64- icon : Shield ,
65- color : 'rose'
66- } ,
67- ] ;
19+ function PrivacyRow ( { icon, title, description, checked, onChange } : PrivacyRowProps ) {
20+ return (
21+ < div className = { S . toggleRow } >
22+ < div className = "flex items-center space-x-3 flex-1 min-w-0" >
23+ < div className = "p-2 bg-zinc-700/50 rounded-lg flex-shrink-0" >
24+ { icon }
25+ </ div >
26+ < div className = "min-w-0 flex-1" >
27+ < h4 className = "text-white font-medium text-sm truncate" > { title } </ h4 >
28+ < p className = "text-zinc-400 text-xs mt-0.5 line-clamp-2" > { description } </ p >
29+ </ div >
30+ </ div >
31+ < div className = "ml-4 flex-shrink-0" >
32+ < Toggle checked = { checked } onChange = { onChange } activeColor = "bg-green-600" />
33+ </ div >
34+ </ div >
35+ ) ;
36+ }
6837
69- const colorClasses : Record < string , string > = {
70- blue : 'bg-blue-500/10 text-blue-500' ,
71- yellow : 'bg-yellow-500/10 text-yellow-500' ,
72- purple : 'bg-purple-500/10 text-purple-500' ,
73- emerald : 'bg-emerald-500/10 text-emerald-500' ,
74- rose : 'bg-rose-500/10 text-rose-500' ,
75- } ;
38+ export default function PrivacySettings ( { settings, onChange } : PrivacySettingsProps ) {
39+ if ( ! settings ) return null ;
7640
7741 return (
78- < div className = "p-5 space-y-3" >
79- { SETTINGS_MAP . map ( ( item ) => {
80- const isChecked = ! ! settings [ item . id as keyof Settings ] ;
81-
82- return (
83- < div key = { item . id } className = { TOKENS . section } >
84- < div className = "flex items-center justify-between gap-4" >
85- < div className = "flex items-center gap-4 min-w-0" >
86- < div className = { `${ TOKENS . iconBox } ${ colorClasses [ item . color ] } ` } >
87- < item . icon className = "h-5 w-5" />
88- </ div >
89- < div className = "min-w-0" >
90- < h4 className = { TOKENS . label } > { item . label } </ h4 >
91- < p className = { TOKENS . description } > { item . desc } </ p >
92- </ div >
93- </ div >
94-
95- { /* Standardized Toggle */ }
96- < button
97- onClick = { ( ) => toggleSetting ( item . id as keyof Settings ) }
98- className = { `${ TOKENS . toggle . base } ${ isChecked ? 'bg-green-600' : 'bg-zinc-700' } ` }
99- >
100- < div className = { `${ TOKENS . toggle . dot } ${ isChecked ? 'translate-x-5' : 'translate-x-0' } ` } />
101- </ button >
102- </ div >
103- </ div >
104- ) ;
105- } ) }
42+ < div className = "space-y-3" >
43+ < PrivacyRow
44+ icon = { < User className = "w-5 h-5 text-zinc-300" /> }
45+ title = "Display Statistics on Profile"
46+ description = "Show your statistics (e.g., sessions created, time controlling, total flights) on your profile page."
47+ checked = { settings . displayStatsOnProfile ?? true }
48+ onChange = { ( checked ) => onChange ( { ...settings , displayStatsOnProfile : checked } ) }
49+ />
50+ < PrivacyRow
51+ icon = { < Star className = "w-5 h-5 text-zinc-300" /> }
52+ title = "Display Controller Rating on Profile"
53+ description = "Show your average controller rating and total ratings on your profile page."
54+ checked = { settings . displayControllerRatingOnProfile ?? true }
55+ onChange = { ( checked ) => onChange ( { ...settings , displayControllerRatingOnProfile : checked } ) }
56+ />
57+ < PrivacyRow
58+ icon = { < Link2 className = "w-5 h-5 text-zinc-300" /> }
59+ title = "Display Linked Accounts on Profile"
60+ description = "Show your linked accounts (e.g., Roblox, VATSIM) on your profile page."
61+ checked = { settings . displayLinkedAccountsOnProfile ?? true }
62+ onChange = { ( checked ) => onChange ( { ...settings , displayLinkedAccountsOnProfile : checked } ) }
63+ />
64+ < PrivacyRow
65+ icon = { < Image className = "w-5 h-5 text-zinc-300" /> }
66+ title = "Display Background Image on Profile"
67+ description = "Show your selected background image in your profile header."
68+ checked = { settings . displayBackgroundOnProfile ?? true }
69+ onChange = { ( checked ) => onChange ( { ...settings , displayBackgroundOnProfile : checked } ) }
70+ />
71+ < PrivacyRow
72+ icon = { < Shield className = "w-5 h-5 text-zinc-300" /> }
73+ title = "Hide from Leaderboard"
74+ description = "Opt out of appearing in the homepage leaderboard rankings."
75+ checked = { settings . hideFromLeaderboard ?? false }
76+ onChange = { ( checked ) => onChange ( { ...settings , hideFromLeaderboard : checked } ) }
77+ />
10678 </ div >
10779 ) ;
108- }
80+ }
0 commit comments