Yaltopia-Tickets-App/app/profile.tsx
2026-06-05 13:39:37 +03:00

284 lines
8.3 KiB
TypeScript

import React, { useState } from "react";
import { View, ScrollView, Pressable, Image } from "react-native";
import { useSirouRouter } from "@sirou/react-native";
import { AppRoutes } from "@/lib/routes";
import { Text } from "@/components/ui/text";
import {
ArrowLeft,
Settings,
ChevronRight,
HelpCircle,
History,
LogOut,
User,
Lock,
Globe,
Building2,
Users,
} from "@/lib/icons";
import { ScreenWrapper } from "@/components/ScreenWrapper";
import { useColorScheme } from "nativewind";
import { saveTheme, AppTheme } from "@/lib/theme";
import { useAuthStore } from "@/lib/auth-store";
import { usePinStore } from "@/lib/pin-store";
import { useLanguageStore, AppLanguage } from "@/lib/language-store";
import { LanguageModal } from "@/components/LanguageModal";
import { ThemeModal } from "@/components/ThemeModal";
const AVATAR_FALLBACK_BASE =
"https://ui-avatars.com/api/?background=ea580c&color=fff&name=";
const THEME_OPTIONS = [
{ value: "light", label: "Light" },
{ value: "dark", label: "Dark" },
{ value: "system", label: "System Default" },
] as const;
type ThemeOption = (typeof THEME_OPTIONS)[number]["value"];
const LANGUAGE_OPTIONS = [
{ value: "en", label: "English" },
{ value: "am", label: "Amharic" },
] as const;
type LanguageOption = (typeof LANGUAGE_OPTIONS)[number]["value"];
function MenuGroup({
label,
children,
}: {
label: string;
children: React.ReactNode;
}) {
return (
<View className="mb-5">
<Text className="text-[16px] font-sans-bold text-foreground mb-2 px-1">
{label}
</Text>
<View className="rounded-[10px] border border-border bg-card overflow-hidden">
{children}
</View>
</View>
);
}
function MenuItem({
icon,
label,
sublabel,
onPress,
right,
destructive = false,
isLast = false,
}: {
icon: React.ReactNode;
label: string;
sublabel?: string;
onPress?: () => void;
right?: React.ReactNode;
destructive?: boolean;
isLast?: boolean;
}) {
return (
<Pressable
onPress={onPress}
className={`flex-row items-center px-4 py-3 ${
!isLast ? "border-b border-border/40" : ""
}`}
>
<View className="h-9 w-9 rounded-[8px] items-center justify-center mr-3">
{icon}
</View>
<View className="flex-1">
<Text
className={`text-sm font-sans-bold ${destructive ? "text-red-500" : "text-foreground"}`}
>
{label}
</Text>
{sublabel ? (
<Text className="text-[11px] font-sans-bold text-muted-foreground mt-0.5">
{sublabel}
</Text>
) : null}
</View>
{right !== undefined ? (
right
) : (
<ChevronRight color={destructive ? "#ef4444" : "#94a3b8"} size={18} />
)}
</Pressable>
);
}
export default function ProfileScreen() {
const nav = useSirouRouter<AppRoutes>();
const { user, logout } = useAuthStore();
const { setColorScheme, colorScheme } = useColorScheme();
const { language, setLanguage } = useLanguageStore();
const [themeSheetVisible, setThemeSheetVisible] = useState(false);
const [languageSheetVisible, setLanguageSheetVisible] = useState(false);
const currentTheme: ThemeOption = (colorScheme as ThemeOption) ?? "system";
const currentLanguage: LanguageOption = (language as LanguageOption) ?? "en";
const handleThemeSelect = (val: AppTheme) => {
setColorScheme(val);
saveTheme(val);
};
const iconColor = colorScheme === "dark" ? "#f8fafc" : "#0f172a";
return (
<ScreenWrapper className="bg-background">
<View className="px-6 pt-4 flex-row justify-between items-center">
<Pressable
onPress={() => nav.back()}
className="h-10 w-10 rounded-[10px] bg-card items-center justify-center border border-border"
>
<ArrowLeft color={iconColor} size={20} />
</Pressable>
<Text className="text-foreground text-[17px] font-sans-bold tracking-tight">
Profile
</Text>
<Pressable
onPress={() => nav.go("edit-profile")}
className="h-10 w-10 rounded-[10px] bg-card items-center justify-center border border-border"
>
<User color={iconColor} size={18} />
</Pressable>
</View>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={{
paddingHorizontal: 16,
paddingTop: 24,
paddingBottom: 80,
}}
>
<View className="items-center mb-8">
<View className="h-20 w-20 rounded-full overflow-hidden bg-muted mb-3">
<Image
source={{
uri:
user?.avatar ||
`${AVATAR_FALLBACK_BASE}${encodeURIComponent(`${user?.firstName} ${user?.lastName}`)}`,
}}
className="h-full w-full"
/>
</View>
<Text className="text-foreground text-lg font-sans-bold tracking-tight">
{user?.firstName} {user?.lastName}
</Text>
<Text className="text-sm font-sans-bold text-foreground mt-0.5">
{user?.email}
</Text>
</View>
<MenuGroup label="Preferences">
<MenuItem
icon={<Settings color={iconColor} size={17} />}
label="Appearance"
sublabel={
THEME_OPTIONS.find((o) => o.value === currentTheme)?.label ??
"System Default"
}
onPress={() => setThemeSheetVisible(true)}
/>
<MenuItem
icon={<Globe color={iconColor} size={17} />}
label="Language"
sublabel={
LANGUAGE_OPTIONS.find((o) => o.value === currentLanguage)
?.label ?? "English"
}
onPress={() => setLanguageSheetVisible(true)}
/>
<MenuItem
icon={<Lock color={iconColor} size={17} />}
label="Password"
sublabel="Change your password"
onPress={() => nav.go("change-pin")}
/>
{/* <MenuItem
icon={<Lock color={iconColor} size={17} />}
label="Lock Now"
sublabel="Lock screen immediately"
onPress={() => {
usePinStore.getState().lock();
nav.go("pin-lock");
}}
isLast
/> */}
</MenuGroup>
<MenuGroup label="Company">
<MenuItem
icon={<Building2 color={iconColor} size={17} />}
label="Overview"
sublabel="View company details"
onPress={() => nav.go("company-details")}
/>
{/* <MenuItem
icon={<Building2 color={iconColor} size={17} />}
label="Edit Company Info"
sublabel="Update business details"
onPress={() => nav.go("company/edit")}
/> */}
<MenuItem
icon={<Users color={iconColor} size={17} />}
label="Workers"
sublabel="Manage team members"
onPress={() => nav.go("team/index")}
isLast
/>
</MenuGroup>
<MenuGroup label="Support & Legal">
<MenuItem
icon={<HelpCircle color={iconColor} size={17} />}
label="Help & Support"
sublabel="Create support tickets"
onPress={() => nav.go("help")}
/>
<MenuItem
icon={<Globe color={iconColor} size={17} />}
label="FAQ"
sublabel="Quick Answers"
onPress={() => nav.go("faq")}
isLast
/>
</MenuGroup>
<View className="rounded-[10px] border border-border bg-card overflow-hidden">
<MenuItem
icon={<LogOut color="#ef4444" size={17} />}
label="Log Out"
destructive
onPress={async () => {
await logout();
nav.go("login");
}}
right={null}
isLast
/>
</View>
</ScrollView>
<ThemeModal
visible={themeSheetVisible}
current={currentTheme}
onSelect={(theme) => handleThemeSelect(theme)}
onClose={() => setThemeSheetVisible(false)}
/>
<LanguageModal
visible={languageSheetVisible}
current={currentLanguage}
onSelect={(lang) => setLanguage(lang)}
onClose={() => setLanguageSheetVisible(false)}
/>
</ScreenWrapper>
);
}