import { Ionicons } from '@expo/vector-icons'; import { router, useLocalSearchParams } from 'expo-router'; import { useCallback, useEffect, useState } from 'react'; import { ActivityIndicator, Alert, StyleSheet, View } from 'react-native'; import { AppHeader, AppText, Button, Card, EmptyState, FormField, IconButton, InlineBanner, ProgressBar, Screen, StatusPill, SubjectBadge, colors, radius, spacing, type SemanticTone, } from '@/components/ui'; import { formatSessionDate } from '@/lib/date'; import { attendanceMessage, attendanceTone, subjectToneFor } from '@/lib/design'; import { collegeApi, type AttendanceStatus } from '@/lib/api'; type Details = Awaited>; const initials = (value: string) => value.trim().split(/\s+/).filter(Boolean).map((word) => word[0]).join('').toUpperCase().slice(0, 6); const statusConfig: Record = { pending: { label: 'Not marked', tone: 'warning', icon: 'time' }, attended: { label: 'Attended', tone: 'success', icon: 'checkmark-circle' }, absent: { label: 'Absent', tone: 'danger', icon: 'close-circle' }, cancelled: { label: 'Cancelled', tone: 'neutral', icon: 'remove-circle' }, }; export default function SubjectDetailsScreen() { const { id } = useLocalSearchParams<{ id: string }>(); const subjectId = Number(id); const [data, setData] = useState
(null); const [loading, setLoading] = useState(true); const [loadError, setLoadError] = useState(''); const [editing, setEditing] = useState(false); const [name, setName] = useState(''); const [code, setCode] = useState(''); const [shortName, setShortName] = useState(''); const [classType, setClassType] = useState('Lecture'); const [defaultRoom, setDefaultRoom] = useState(''); const [shortEdited, setShortEdited] = useState(false); const [saving, setSaving] = useState(false); const [formError, setFormError] = useState(''); const load = useCallback(() => { if (!Number.isFinite(subjectId)) return; setLoading(true); setLoadError(''); collegeApi.subject(subjectId) .then((subject) => { setData(subject); setName(subject.name); setCode(subject.code); setShortName(subject.shortName || initials(subject.name)); setClassType(subject.classType || 'Lecture'); setDefaultRoom(subject.defaultRoom || ''); setShortEdited(Boolean(subject.shortName)); }) .catch((error: Error) => setLoadError(error.message)) .finally(() => setLoading(false)); }, [subjectId]); useEffect(() => { load(); }, [load]); const changeName = (value: string) => { setName(value); if (!shortEdited) setShortName(initials(value)); }; const save = async () => { if (!name.trim() || !code.trim() || !shortName.trim() || !classType.trim()) { setFormError('Name, subject code, short name, and class type are required.'); return; } setSaving(true); setFormError(''); try { const tone = subjectToneFor(subjectId, data?.color); await collegeApi.updateSubject(subjectId, { name, code, shortName, classType, defaultRoom, color: colors.subject[tone].accent }); setEditing(false); load(); } catch (error) { setFormError(error instanceof Error ? error.message : 'Please try again.'); } finally { setSaving(false); } }; const deleteSubject = () => { Alert.alert( 'Delete subject?', `Are you sure you want to delete ${data?.name}? This will remove its timetable classes and attendance records.`, [ { text: 'Cancel', style: 'cancel' }, { text: 'Delete', style: 'destructive', onPress: async () => { try { await collegeApi.deleteSubject(subjectId); router.back(); } catch (err) { Alert.alert('Couldn’t delete subject', err instanceof Error ? err.message : 'Please try again.'); } }, }, ] ); }; if (loading && !data) return Loading subject…; if (!data) return router.back()} />} /> } style={styles.error} /> ; const tone = subjectToneFor(data.id, data.color); const palette = colors.subject[tone]; const summaryTone = attendanceTone(data.summary.percentage, data.summary.total); const summaryCopy = attendanceMessage(data.summary.percentage, data.summary.total); return router.back()} />} trailing={ { setEditing((value) => !value); setFormError(''); }} />} /> {data.name} {data.code} · {data.shortName || initials(data.name)} {data.summary.total ? `${data.summary.percentage}%` : '—'} Attendance {editing ? Edit subject {formError ? : null} setCode(value.toUpperCase())} placeholder="e.g. CS201" autoCapitalize="characters" /> { setShortEdited(true); setShortName(value.toUpperCase().slice(0, 6)); }} placeholder="e.g. DS" hint="Up to 6 characters; used in compact schedule views." autoCapitalize="characters" />