push
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
View, Text, ScrollView, TouchableOpacity, Linking, ActivityIndicator, Alert, StyleSheet, Platform,
|
||||
View, Text, ScrollView, TouchableOpacity, Linking, ActivityIndicator, Alert, Share, StyleSheet, Platform,
|
||||
} from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import { useLocalSearchParams, useRouter, Stack } from 'expo-router'
|
||||
@@ -10,6 +10,7 @@ import { Badge } from '@/components/ui/Badge'
|
||||
import { TERMIN_TYP_LABELS } from '@innungsapp/shared/types'
|
||||
import { format } from 'date-fns'
|
||||
import { de } from 'date-fns/locale'
|
||||
import * as Calendar from 'expo-calendar'
|
||||
|
||||
export default function TerminDetailScreen() {
|
||||
const { id } = useLocalSearchParams<{ id: string }>()
|
||||
@@ -29,6 +30,63 @@ export default function TerminDetailScreen() {
|
||||
const datum = new Date(termin.datum)
|
||||
const isPast = datum < new Date()
|
||||
|
||||
const handleAddToCalendar = async () => {
|
||||
try {
|
||||
const { status } = await Calendar.requestCalendarPermissionsAsync()
|
||||
if (status !== 'granted') {
|
||||
Alert.alert('Fehler', 'Kalender-Berechtigung wurde verweigert.')
|
||||
return
|
||||
}
|
||||
|
||||
const startDate = new Date(termin.datum)
|
||||
let endDate = new Date(termin.datum)
|
||||
|
||||
if (termin.uhrzeit) {
|
||||
const [hours, minutes] = termin.uhrzeit.split(':').map(Number)
|
||||
startDate.setHours(hours || 0, minutes || 0)
|
||||
|
||||
if (termin.endeUhrzeit) {
|
||||
const [endHours, endMinutes] = termin.endeUhrzeit.split(':').map(Number)
|
||||
endDate.setHours(endHours || 0, endMinutes || 0)
|
||||
} else {
|
||||
endDate.setHours((hours || 0) + 1, minutes || 0)
|
||||
}
|
||||
} else {
|
||||
endDate.setDate(startDate.getDate() + 1)
|
||||
}
|
||||
|
||||
let calendarId
|
||||
if (Platform.OS === 'ios') {
|
||||
const defaultCalendar = await Calendar.getDefaultCalendarAsync()
|
||||
calendarId = defaultCalendar.id
|
||||
} else {
|
||||
const calendars = await Calendar.getCalendarsAsync(Calendar.EntityTypes.EVENT)
|
||||
// Try to prefer primary or typical default calendar
|
||||
const primary = calendars.find(c => c.isPrimary) || calendars.find(c => c.accessLevel === 'owner') || calendars[0]
|
||||
calendarId = primary?.id
|
||||
}
|
||||
|
||||
if (!calendarId) {
|
||||
Alert.alert('Fehler', 'Kein beschreibbarer Kalender gefunden.')
|
||||
return
|
||||
}
|
||||
|
||||
await Calendar.createEventAsync(calendarId, {
|
||||
title: termin.titel,
|
||||
startDate,
|
||||
endDate,
|
||||
allDay: !termin.uhrzeit,
|
||||
location: [termin.ort, termin.adresse].filter(Boolean).join(', '),
|
||||
notes: termin.beschreibung || undefined,
|
||||
})
|
||||
|
||||
Alert.alert('Erfolg', 'Der Termin wurde in den Kalender eingetragen.')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
Alert.alert('Fehler', 'Der Termin konnte nicht eingetragen werden.')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack.Screen options={{ headerShown: false }} />
|
||||
@@ -39,7 +97,21 @@ export default function TerminDetailScreen() {
|
||||
<Ionicons name="arrow-back" size={24} color="#0F172A" />
|
||||
</TouchableOpacity>
|
||||
<View style={styles.headerSpacer} />
|
||||
<TouchableOpacity style={styles.shareButton}>
|
||||
<TouchableOpacity
|
||||
style={styles.shareButton}
|
||||
onPress={() => {
|
||||
const lines: string[] = []
|
||||
lines.push(`📅 ${termin.titel}`)
|
||||
lines.push(format(datum, 'EEEE, d. MMMM yyyy', { locale: de }))
|
||||
if (termin.uhrzeit) {
|
||||
lines.push(`🕐 ${termin.uhrzeit}${termin.endeUhrzeit ? ` – ${termin.endeUhrzeit}` : ''} Uhr`)
|
||||
}
|
||||
if (termin.ort) lines.push(`📍 ${termin.ort}`)
|
||||
if (termin.adresse) lines.push(` ${termin.adresse}`)
|
||||
if (termin.beschreibung) lines.push(`\n${termin.beschreibung}`)
|
||||
Share.share({ message: lines.join('\n') })
|
||||
}}
|
||||
>
|
||||
<Ionicons name="share-outline" size={24} color="#0F172A" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
@@ -156,11 +228,13 @@ export default function TerminDetailScreen() {
|
||||
isAngemeldet={termin.isAngemeldet}
|
||||
onToggle={() => mutate({ terminId: id })}
|
||||
isLoading={isPending}
|
||||
maxTeilnehmer={termin.maxTeilnehmer}
|
||||
teilnehmerAnzahl={termin.teilnehmerAnzahl}
|
||||
/>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
style={styles.calendarButton}
|
||||
onPress={() => Alert.alert('Kalender', 'Funktion folgt in Kürze')}
|
||||
onPress={handleAddToCalendar}
|
||||
>
|
||||
<Ionicons name="calendar-outline" size={24} color="#0F172A" />
|
||||
</TouchableOpacity>
|
||||
|
||||
@@ -52,8 +52,11 @@ export default function TermineScreen() {
|
||||
data={data ?? []}
|
||||
keyExtractor={(item) => item.id}
|
||||
contentContainerStyle={styles.list}
|
||||
initialNumToRender={10}
|
||||
maxToRenderPerBatch={10}
|
||||
windowSize={5}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={isRefetching} onRefresh={refetch} tintColor="#003B7E" />
|
||||
<RefreshControl refreshing={isRefetching} onRefresh={refetch} tintColor="#003B7E" progressViewOffset={50} />
|
||||
}
|
||||
renderItem={({ item }) => (
|
||||
<TerminCard
|
||||
|
||||
Reference in New Issue
Block a user