ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
1import { Upload, Sparkles, ChevronRight, Database } from "lucide-react"; 2import { ATPROTO_APPS } from "../config/atprotoApps"; 3import type { Upload as UploadType } from "../types"; 4import FaviconIcon from "../components/FaviconIcon"; 5import type { UserSettings } from "../types/settings"; 6import { UploadHistorySkeleton } from "./common/LoadingSkeleton"; 7import { getPlatformColor } from "../lib/utils/platform"; 8import { formatRelativeTime } from "../lib/utils/date"; 9import EmptyState from "./common/EmptyState"; 10import SetupPrompt from "./common/SetupPrompt"; 11import Card from "./common/Card"; 12import Badge from "./common/Badge"; 13import CardItem from "./common/CardItem"; 14 15interface HistoryTabProps { 16 uploads: UploadType[]; 17 wizardCompleted: boolean; 18 onShowWizard: () => void; 19 isLoading: boolean; 20 userSettings: UserSettings; 21 onLoadUpload: (uploadId: string) => void; 22} 23 24export default function HistoryTab({ 25 uploads, 26 wizardCompleted, 27 onShowWizard, 28 isLoading, 29 userSettings, 30 onLoadUpload, 31}: HistoryTabProps) { 32 return ( 33 <div className="p-6"> 34 {/* Setup Assistant Banner - Only show if wizard not completed */} 35 {!wizardCompleted && ( 36 <SetupPrompt 37 variant="banner" 38 isCompleted={wizardCompleted} 39 onShowWizard={onShowWizard} 40 /> 41 )} 42 43 <div className="flex items-center space-x-3 mb-4"> 44 <div> 45 <h2 className="text-xl font-bold text-purple-950 dark:text-cyan-50"> 46 Previously Uploaded 47 </h2> 48 <p className="text-sm text-purple-750 dark:text-cyan-250"> 49 Reconnect with your light trail 50 </p> 51 </div> 52 </div> 53 54 {/* Data Storage Disabled Notice */} 55 {!userSettings.saveData && ( 56 <Card className="mb-4 p-4 border-orange-650/50 dark:border-amber-400/50 bg-purple-100/50 dark:bg-slate-900/50"> 57 <div className="flex items-start space-x-3"> 58 <Database className="w-5 h-5 text-orange-600 dark:text-amber-400 flex-shrink-0 mt-0.5" /> 59 <div> 60 <h3 className="font-semibold text-purple-950 dark:text-cyan-50 mb-1"> 61 Data Storage Disabled 62 </h3> 63 <p className="text-sm text-purple-900 dark:text-cyan-100"> 64 You've disabled data storage in your settings. Enable "Save my 65 data" in the Settings tab to save your upload history. 66 </p> 67 </div> 68 </div> 69 </Card> 70 )} 71 72 {isLoading ? ( 73 <div className="space-y-3"> 74 {[...Array(3)].map((_, i) => ( 75 <UploadHistorySkeleton key={i} /> 76 ))} 77 </div> 78 ) : uploads.length === 0 ? ( 79 <EmptyState 80 icon={Upload} 81 title="No previous uploads yet" 82 message="Upload your first file to get started" 83 /> 84 ) : ( 85 <div className="space-y-3"> 86 {uploads.map((upload) => { 87 const destApp = 88 ATPROTO_APPS[ 89 userSettings.platformDestinations[ 90 upload.sourcePlatform as keyof typeof userSettings.platformDestinations 91 ] 92 ]; 93 return ( 94 <Card 95 key={upload.uploadId} 96 variant="upload" 97 className="w-full" 98 > 99 <CardItem 100 padding="p-4" 101 badgeIndentClass="sm:pl-[56px]" 102 onClick={() => onLoadUpload(upload.uploadId)} 103 avatar={ 104 <div 105 className={`w-10 h-10 bg-gradient-to-r ${getPlatformColor(upload.sourcePlatform)} rounded-xl flex items-center justify-center flex-shrink-0 shadow-md`} 106 > 107 <Sparkles className="w-6 h-6 text-white" /> 108 </div> 109 } 110 content={ 111 <> 112 <div className="flex flex-wrap items-start justify-between gap-x-4 gap-y-2"> 113 <div className="font-semibold text-purple-950 dark:text-cyan-50 capitalize leading-tight"> 114 {upload.sourcePlatform} 115 </div> 116 <div className="flex items-center gap-2 flex-shrink-0"> 117 <span className="text-sm text-purple-750 dark:text-cyan-250 whitespace-nowrap flex-shrink-0"> 118 {upload.matchedUsers}{" "} 119 {upload.matchedUsers === 1 ? "match" : "matches"} 120 </span> 121 </div> 122 </div> 123 {destApp && ( 124 <a 125 href={destApp.link} 126 target="_blank" 127 rel="noopener noreferrer" 128 onClick={(e) => e.stopPropagation()} 129 className="text-sm text-purple-750 dark:text-cyan-250 hover:underline leading-tight flex items-center space-x-1 w-fit" 130 > 131 <span>{destApp.action} on</span> 132 133 <FaviconIcon 134 url={destApp.icon} 135 alt={destApp.name} 136 className="w-3 h-3 mb-0.5 flex-shrink-0" 137 /> 138 139 <span>{destApp.name}</span> 140 </a> 141 )} 142 </> 143 } 144 badges={ 145 <> 146 <Badge variant="info"> 147 {upload.totalUsers}{" "} 148 {upload.totalUsers === 1 ? "user found" : "users found"} 149 </Badge> 150 <Badge variant="info"> 151 Uploaded {formatRelativeTime(upload.createdAt)} 152 </Badge> 153 </> 154 } 155 /> 156 </Card> 157 ); 158 })} 159 </div> 160 )} 161 </div> 162 ); 163}