stadtwerke/innungsapp/apps/mobile/app/(app)/stellen/index.tsx

134 lines
3.4 KiB
TypeScript

import { View, Text, FlatList, RefreshControl, StyleSheet } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import { useRouter } from 'expo-router'
import { useStellenListe } from '@/hooks/useStellen'
import { StelleCard } from '@/components/stellen/StelleCard'
import { EmptyState } from '@/components/ui/EmptyState'
import { LoadingSpinner } from '@/components/ui/LoadingSpinner'
export default function StellenScreen() {
const router = useRouter()
const { data, isLoading, refetch, isRefetching } = useStellenListe()
const totalStellen = data?.reduce((sum, s) => sum + s.stellenAnz, 0) ?? 0
return (
<SafeAreaView style={styles.safeArea} edges={['top']}>
{/* Header */}
<View style={styles.header}>
<View style={styles.titleRow}>
<View style={styles.titleBlock}>
<Text style={styles.screenTitle}>Lehrlingsbörse</Text>
<Text style={styles.subtitle}>Ausbildungsplätze in deiner Innung</Text>
</View>
{/* Counter */}
{totalStellen > 0 && (
<View style={styles.counter}>
<Text style={styles.counterNumber}>{totalStellen}</Text>
<Text style={styles.counterLabel}>Stellen</Text>
</View>
)}
</View>
</View>
<View style={styles.divider} />
{isLoading ? (
<LoadingSpinner />
) : (
<FlatList
data={data ?? []}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.list}
initialNumToRender={10}
maxToRenderPerBatch={10}
windowSize={5}
refreshControl={
<RefreshControl refreshing={isRefetching} onRefresh={refetch} tintColor="#003B7E" progressViewOffset={50} />
}
renderItem={({ item }) => (
<StelleCard
stelle={item}
onPress={() => router.push(`/(app)/stellen/${item.id}` as never)}
/>
)}
ListEmptyComponent={
<EmptyState
icon="school-outline"
title="Keine Angebote"
subtitle="Aktuell keine Ausbildungsplätze verfügbar"
/>
}
/>
)}
</SafeAreaView>
)
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: '#F8FAFC',
},
header: {
backgroundColor: '#FFFFFF',
paddingHorizontal: 20,
paddingTop: 18,
paddingBottom: 16,
},
titleRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
titleBlock: {
flex: 1,
},
screenTitle: {
fontSize: 26,
fontWeight: '800',
color: '#0F172A',
letterSpacing: -0.5,
},
subtitle: {
fontSize: 13,
color: '#64748B',
marginTop: 2,
},
counter: {
backgroundColor: '#003B7E',
borderRadius: 14,
paddingHorizontal: 14,
paddingVertical: 8,
alignItems: 'center',
minWidth: 56,
shadowColor: '#003B7E',
shadowOffset: { width: 0, height: 3 },
shadowOpacity: 0.25,
shadowRadius: 8,
elevation: 4,
},
counterNumber: {
color: '#FFFFFF',
fontSize: 22,
fontWeight: '800',
lineHeight: 24,
},
counterLabel: {
color: 'rgba(255,255,255,0.75)',
fontSize: 9,
fontWeight: '600',
letterSpacing: 0.5,
},
divider: {
height: 1,
backgroundColor: '#E2E8F0',
},
list: {
padding: 16,
gap: 10,
},
})