ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
1import { Settings as SettingsIcon, ChevronRight } from "lucide-react"; 2import { PLATFORMS } from "../config/platforms"; 3import { ATPROTO_APPS } from "../config/atprotoApps"; 4import type { UserSettings, PlatformDestinations } from "../types/settings"; 5import Section from "../components/common/Section"; 6import Card from "../components/common/Card"; 7import Badge from "../components/common/Badge"; 8import PlatformBadge from "../components/common/PlatformBadge"; 9import Toggle from "../components/common/Toggle"; 10import DropdownWithIcons from "../components/common/DropdownWithIcons"; 11import type { DropdownOptionWithIcon } from "../components/common/DropdownWithIcons"; 12 13interface SettingsPageProps { 14 userSettings: UserSettings; 15 onSettingsUpdate: (settings: Partial<UserSettings>) => void; 16 onOpenWizard: () => void; 17} 18 19export default function SettingsPage({ 20 userSettings, 21 onSettingsUpdate, 22 onOpenWizard, 23}: SettingsPageProps) { 24 const handleDestinationChange = (platform: string, destination: string) => { 25 onSettingsUpdate({ 26 platformDestinations: { 27 ...userSettings.platformDestinations, 28 [platform]: destination, 29 }, 30 }); 31 }; 32 33 // Prepare app options with icons for dropdown 34 const appOptions: DropdownOptionWithIcon[] = Object.values(ATPROTO_APPS).map( 35 (app) => ({ 36 value: app.id, 37 label: app.name, 38 icon: app.icon, 39 }) 40 ); 41 42 return ( 43 <div className="space-y-0"> 44 {/* Setup Assistant Section */} 45 <Section 46 title="Setup Assistant" 47 description="Quick configuration wizard" 48 divider 49 > 50 <Card 51 variant="upload" 52 onClick={onOpenWizard} 53 className="w-full flex items-start space-x-4 p-4 text-left" 54 > 55 <div className="w-12 h-12 bg-firefly-banner dark:bg-firefly-banner-dark rounded-xl flex items-center justify-center flex-shrink-0 shadow-md"> 56 <SettingsIcon className="w-6 h-6 text-white" /> 57 </div> 58 <div className="flex-1 min-w-0"> 59 <div className="flex flex-wrap items-start justify-between gap-x-4 gap-y-2 mb-1"> 60 <div className="font-semibold text-purple-950 dark:text-cyan-50 leading-tight"> 61 Run Setup Wizard 62 </div> 63 </div> 64 <p className="text-sm text-purple-750 dark:text-cyan-250 leading-tight"> 65 Configure platform destinations, privacy, and automation settings 66 </p> 67 </div> 68 <ChevronRight className="w-5 h-5 text-purple-500 dark:text-cyan-400 flex-shrink-0 self-center" /> 69 </Card> 70 71 {/* Current Configuration */} 72 <div className="mt-2 py-2 px-3"> 73 <h3 className="font-semibold text-purple-950 dark:text-cyan-50 mb-3"> 74 Current Configuration 75 </h3> 76 <div className="gap-8 flex flex-wrap text-sm"> 77 <div> 78 <div className="text-purple-750 dark:text-cyan-250 mb-1"> 79 Data Storage 80 </div> 81 <Badge variant="status"> 82 {userSettings.saveData ? "✅ Enabled" : "❌ Disabled"} 83 </Badge> 84 </div> 85 <div> 86 <div className="text-purple-750 dark:text-cyan-250 mb-1"> 87 Automation 88 </div> 89 <Badge variant="status"> 90 {userSettings.enableAutomation 91 ? `${userSettings.automationFrequency}` 92 : "❌ Disabled"} 93 </Badge> 94 </div> 95 <div> 96 <div className="text-purple-750 dark:text-cyan-250 mb-1"> 97 Wizard 98 </div> 99 <Badge variant="status"> 100 {userSettings.wizardCompleted ? "✅ Completed" : "⏳ Pending"} 101 </Badge> 102 </div> 103 </div> 104 </div> 105 </Section> 106 107 {/* Match Destinations Section */} 108 <Section 109 title="Match Destinations" 110 description="Where matches should go for each platform" 111 divider 112 > 113 <Card className="mt-3 px-3 py-2 rounded-lg border-orange-650/50 dark:border-amber-400/50"> 114 <p className="text-sm text-purple-900 dark:text-cyan-100"> 115 💡 <strong>Tip:</strong> Choose different apps for different 116 platforms based on content type. For example, send TikTok matches to 117 Spark for video content. 118 </p> 119 </Card> 120 121 <div className="py-2 space-y-0"> 122 {Object.entries(PLATFORMS).map(([key, p]) => { 123 const currentDestination = 124 userSettings.platformDestinations[ 125 key as keyof PlatformDestinations 126 ]; 127 128 return ( 129 <div 130 key={key} 131 className="flex items-center justify-between gap-3 px-3 py-2 rounded-xl transition-colors" 132 > 133 <PlatformBadge 134 platformKey={key} 135 size="sm" 136 className="flex-1 min-w-0" 137 /> 138 <DropdownWithIcons 139 value={currentDestination} 140 onChange={(value) => handleDestinationChange(key, value)} 141 options={appOptions} 142 className="w-48" 143 /> 144 </div> 145 ); 146 })} 147 </div> 148 </Section> 149 150 {/* Privacy & Data Section */} 151 <Section 152 title="Privacy & Data" 153 description="Control how your data is stored" 154 > 155 <div className="px-3 space-y-4"> 156 {/* Save Data Toggle */} 157 <Toggle 158 checked={userSettings.saveData} 159 onChange={(checked) => onSettingsUpdate({ saveData: checked })} 160 label="Save my data" 161 description="Store your following lists for periodic re-checking and new match notifications" 162 id="settings-save-data" 163 /> 164 165 {/* Automation Toggle */} 166 <div> 167 <Toggle 168 checked={userSettings.enableAutomation} 169 onChange={(checked) => 170 onSettingsUpdate({ enableAutomation: checked }) 171 } 172 label="Notify about new matches" 173 description="Get DMs when people you follow join the ATmosphere" 174 disabled={!userSettings.saveData} 175 id="settings-automation" 176 /> 177 178 {userSettings.enableAutomation && ( 179 <div className="flex items-center gap-3 px-0 mt-4"> 180 <label className="text-sm font-medium text-purple-950 dark:text-cyan-50 whitespace-nowrap"> 181 Frequency 182 </label> 183 <select 184 value={userSettings.automationFrequency} 185 onChange={(e) => 186 onSettingsUpdate({ 187 automationFrequency: e.target.value as 188 | "Weekly" 189 | "Monthly" 190 | "Quarterly", 191 }) 192 } 193 className="flex-1 px-3 py-2 bg-white dark:bg-slate-800 border border-cyan-500/30 dark:border-purple-500/30 rounded-lg text-sm text-purple-950 dark:text-cyan-50 hover:border-cyan-400 dark:hover:border-purple-400 focus:outline-none focus:ring-2 focus:ring-orange-500 dark:focus:ring-amber-400 transition-colors" 194 > 195 <option value="daily">Check daily</option> 196 <option value="weekly">Check weekly</option> 197 <option value="monthly">Check monthly</option> 198 </select> 199 </div> 200 )} 201 </div> 202 </div> 203 </Section> 204 </div> 205 ); 206}