Yaltopia-Tickets-App/app/notifications/settings.tsx
2026-03-11 22:48:53 +03:00

222 lines
7.8 KiB
TypeScript

import React, { useCallback, useEffect, useState } from "react";
import {
View,
ScrollView,
Switch,
ActivityIndicator,
TextInput,
useColorScheme,
Pressable,
} from "react-native";
import { useSirouRouter } from "@sirou/react-native";
import { AppRoutes } from "@/lib/routes";
import { Text } from "@/components/ui/text";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { ScreenWrapper } from "@/components/ScreenWrapper";
import { StandardHeader } from "@/components/StandardHeader";
import { api } from "@/lib/api";
import { Bell, CalendarSearch, FileText, Newspaper, ChevronRight } from "@/lib/icons";
import { getPlaceholderColor } from "@/lib/colors";
import { PickerModal, SelectOption } from "@/components/PickerModal";
type NotificationSettings = {
id: string;
invoiceReminders: boolean;
daysBeforeDueDate: number;
newsAlerts: boolean;
reportReady: boolean;
userId: string;
createdAt: string;
updatedAt: string;
};
export default function NotificationSettingsScreen() {
const nav = useSirouRouter<AppRoutes>();
const colorScheme = useColorScheme();
const isDark = colorScheme === "dark";
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [settings, setSettings] = useState<NotificationSettings | null>(null);
const [invoiceReminders, setInvoiceReminders] = useState(false);
const [daysBeforeDueDate, setDaysBeforeDueDate] = useState("0");
const [newsAlerts, setNewsAlerts] = useState(false);
const [reportReady, setReportReady] = useState(false);
const [daysModalVisible, setDaysModalVisible] = useState(false);
const daysOptions = [
{ label: "1 day", value: "1" },
{ label: "3 days", value: "3" },
{ label: "7 days", value: "7" },
{ label: "14 days", value: "14" },
{ label: "30 days", value: "30" },
];
const loadSettings = useCallback(async () => {
try {
setLoading(true);
const res = await (api as any).notifications.settings();
const data = res?.data ?? res;
setSettings(data);
setInvoiceReminders(Boolean(data?.invoiceReminders));
setNewsAlerts(Boolean(data?.newsAlerts));
setReportReady(Boolean(data?.reportReady));
setDaysBeforeDueDate(String(data?.daysBeforeDueDate ?? 0));
} catch (e) {
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
loadSettings();
}, [loadSettings]);
const onSave = async () => {
setSaving(true);
try {
await api.notifications.update({
body: {
invoiceReminders,
daysBeforeDueDate: parseInt(daysBeforeDueDate),
newsAlerts,
reportReady,
},
});
nav.back();
} finally {
setSaving(false);
}
};
return (
<ScreenWrapper className="bg-background">
<StandardHeader showBack title="Notification settings" />
{loading ? (
<View className="flex-1 items-center justify-center">
<ActivityIndicator />
</View>
) : (
<ScrollView
contentContainerStyle={{ padding: 16, paddingBottom: 110 }}
showsVerticalScrollIndicator={false}
>
<View className="mb-5">
<Text variant="muted" className="text-xs font-semibold mb-2 px-1">
Preferences
</Text>
<Card className="overflow-hidden">
<CardContent className="p-0">
<View className="flex-row items-center px-4 py-3 border-b border-border/40">
<View className="h-9 w-9 rounded-[8px] items-center justify-center mr-3">
<Bell size={17} color="#ea580c" />
</View>
<View className="flex-1">
<Text className="text-foreground font-medium">
Invoice reminders
</Text>
<Text variant="muted" className="text-xs mt-0.5">
Get reminders before invoices are due
</Text>
</View>
<Switch
value={invoiceReminders}
onValueChange={setInvoiceReminders}
trackColor={{ false: "#94a3b8", true: "#ea580c" }}
thumbColor="#ffffff"
/>
</View>
<View className="px-4 py-3 border-b border-border/40">
<View className="flex-row items-center mb-2">
<View className="h-9 w-9 rounded-[8px] items-center justify-center mr-3">
<CalendarSearch size={17} color="#ea580c" />
</View>
<View className="flex-1">
<Text className="text-foreground font-medium">
Days before due date
</Text>
<Text variant="muted" className="text-xs mt-0.5">
Currently: {daysBeforeDueDate} days
</Text>
</View>
<Pressable onPress={() => setDaysModalVisible(true)}>
<ChevronRight size={18} color="#ea580c" />
</Pressable>
</View>
</View>
<View className="flex-row items-center px-4 py-3 border-b border-border/40">
<View className="h-9 w-9 rounded-[8px] items-center justify-center mr-3">
<Newspaper size={17} color="#ea580c" />
</View>
<View className="flex-1">
<Text className="text-foreground font-medium">News alerts</Text>
<Text variant="muted" className="text-xs mt-0.5">
Product updates and announcements
</Text>
</View>
<Switch
value={newsAlerts}
onValueChange={setNewsAlerts}
trackColor={{ false: "#94a3b8", true: "#ea580c" }}
thumbColor="#ffffff"
/>
</View>
<View className="flex-row items-center px-4 py-3">
<View className="h-9 w-9 rounded-[8px] items-center justify-center mr-3">
<FileText size={17} color="#ea580c" />
</View>
<View className="flex-1">
<Text className="text-foreground font-medium">Report ready</Text>
<Text variant="muted" className="text-xs mt-0.5">
Notify when reports are generated
</Text>
</View>
<Switch
value={reportReady}
onValueChange={setReportReady}
trackColor={{ false: "#94a3b8", true: "#ea580c" }}
thumbColor="#ffffff"
/>
</View>
</CardContent>
</Card>
</View>
</ScrollView>
)}
<View className="absolute bottom-0 pb-10 left-0 right-0 p-4 bg-background border-t border-border">
<Button className="bg-primary" onPress={onSave} disabled={saving || loading}>
<Text className="text-white font-semibold">
{saving ? "Saving..." : "Save"}
</Text>
</Button>
</View>
<PickerModal
visible={daysModalVisible}
title="Select Days"
onClose={() => setDaysModalVisible(false)}
>
{daysOptions.map((option) => (
<SelectOption
key={option.value}
label={option.label}
value={option.value}
selected={option.value === daysBeforeDueDate}
onSelect={(value: string) => {
setDaysBeforeDueDate(value);
setDaysModalVisible(false);
}}
/>
))}
</PickerModal>
</ScreenWrapper>
);
}