170 lines
5.7 KiB
TypeScript
170 lines
5.7 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
|
import {
|
|
View,
|
|
ScrollView,
|
|
Pressable,
|
|
TextInput,
|
|
ActivityIndicator,
|
|
RefreshControl,
|
|
useColorScheme,
|
|
} from "react-native";
|
|
import { Text } from "@/components/ui/text";
|
|
import { Card, CardContent } from "@/components/ui/card";
|
|
import { ScreenWrapper } from "@/components/ScreenWrapper";
|
|
import { StandardHeader } from "@/components/StandardHeader";
|
|
import { ShadowWrapper } from "@/components/ShadowWrapper";
|
|
import { useSirouRouter } from "@sirou/react-native";
|
|
import { AppRoutes } from "@/lib/routes";
|
|
import { Stack } from "expo-router";
|
|
import { useAuthStore } from "@/lib/auth-store";
|
|
import { api } from "@/lib/api";
|
|
import { getPlaceholderColor } from "@/lib/colors";
|
|
import {
|
|
UserPlus,
|
|
Search,
|
|
Mail,
|
|
Phone,
|
|
ChevronRight,
|
|
Briefcase,
|
|
Info,
|
|
} from "@/lib/icons";
|
|
|
|
export default function CompanyScreen() {
|
|
const nav = useSirouRouter<AppRoutes>();
|
|
const colorScheme = useColorScheme();
|
|
const isDark = colorScheme === "dark";
|
|
|
|
const [workers, setWorkers] = useState<any[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [refreshing, setRefreshing] = useState(false);
|
|
const [searchQuery, setSearchQuery] = useState("");
|
|
|
|
const fetchWorkers = async () => {
|
|
try {
|
|
const response = await api.users.getAll();
|
|
setWorkers(response.data || []);
|
|
} catch (error) {
|
|
console.error("[CompanyScreen] Error fetching workers:", error);
|
|
} finally {
|
|
setLoading(false);
|
|
setRefreshing(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchWorkers();
|
|
}, []);
|
|
|
|
const onRefresh = () => {
|
|
setRefreshing(true);
|
|
fetchWorkers();
|
|
};
|
|
|
|
const filteredWorkers = workers.filter((worker) => {
|
|
const name = `${worker.firstName} ${worker.lastName}`.toLowerCase();
|
|
const email = (worker.email || "").toLowerCase();
|
|
const query = searchQuery.toLowerCase();
|
|
return name.includes(query) || email.includes(query);
|
|
});
|
|
|
|
return (
|
|
<ScreenWrapper className="bg-background">
|
|
<Stack.Screen options={{ headerShown: false }} />
|
|
<StandardHeader title="Company" showBack rightAction="companyInfo" />
|
|
|
|
<View className="flex-1 px-5 pt-4">
|
|
{/* Search Bar */}
|
|
<ShadowWrapper level="xs">
|
|
<View className="flex-row items-center bg-card rounded-xl px-4 border border-border h-12 mb-6">
|
|
<Search size={18} color={isDark ? "#94a3b8" : "#64748b"} />
|
|
<TextInput
|
|
className="flex-1 ml-3 text-foreground"
|
|
placeholder="Search workers..."
|
|
placeholderTextColor={getPlaceholderColor(isDark)}
|
|
value={searchQuery}
|
|
onChangeText={setSearchQuery}
|
|
/>
|
|
</View>
|
|
</ShadowWrapper>
|
|
|
|
{/* Worker List Header */}
|
|
<View className="flex-row justify-between items-center mb-4">
|
|
<Text variant="h4" className="text-foreground tracking-tight">
|
|
Workers ({filteredWorkers.length})
|
|
</Text>
|
|
</View>
|
|
|
|
{loading ? (
|
|
<View className="flex-1 justify-center items-center">
|
|
<ActivityIndicator color="#ea580c" />
|
|
</View>
|
|
) : (
|
|
<ScrollView
|
|
showsVerticalScrollIndicator={false}
|
|
refreshControl={
|
|
<RefreshControl
|
|
refreshing={refreshing}
|
|
onRefresh={onRefresh}
|
|
tintColor="#ea580c"
|
|
/>
|
|
}
|
|
contentContainerStyle={{ paddingBottom: 100 }}
|
|
>
|
|
{filteredWorkers.length > 0 ? (
|
|
filteredWorkers.map((worker) => (
|
|
<ShadowWrapper key={worker.id} level="xs">
|
|
<Card className="mb-3 overflow-hidden rounded-[12px] bg-card border-0">
|
|
<CardContent className="flex-row items-center p-4">
|
|
<View className="h-12 w-12 rounded-full bg-secondary/50 items-center justify-center mr-4">
|
|
<Text className="text-primary font-bold text-lg">
|
|
{worker.firstName?.[0]}
|
|
{worker.lastName?.[0]}
|
|
</Text>
|
|
</View>
|
|
|
|
<View className="flex-1">
|
|
<Text className="text-foreground font-bold text-base">
|
|
{worker.firstName} {worker.lastName}
|
|
</Text>
|
|
<View className="flex-row items-center mt-1">
|
|
<Text className="text-muted-foreground text-xs bg-secondary px-2 py-0.5 rounded-md uppercase font-bold tracking-widest text-[10px]">
|
|
{worker.role || "WORKER"}
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
|
|
<ChevronRight
|
|
size={18}
|
|
color={isDark ? "#334155" : "#cbd5e1"}
|
|
/>
|
|
</CardContent>
|
|
</Card>
|
|
</ShadowWrapper>
|
|
))
|
|
) : (
|
|
<View className="py-20 items-center">
|
|
<Briefcase
|
|
size={48}
|
|
color={isDark ? "#1e293b" : "#f1f5f9"}
|
|
strokeWidth={1}
|
|
/>
|
|
<Text variant="muted" className="mt-4">
|
|
No workers found
|
|
</Text>
|
|
</View>
|
|
)}
|
|
</ScrollView>
|
|
)}
|
|
</View>
|
|
|
|
{/* Floating Action Button */}
|
|
<Pressable
|
|
onPress={() => nav.go("user/create")}
|
|
className="absolute bottom-8 right-8 h-14 w-14 bg-primary rounded-full items-center justify-center shadow-lg shadow-primary/40"
|
|
>
|
|
<UserPlus size={24} color="white" strokeWidth={2.5} />
|
|
</Pressable>
|
|
</ScreenWrapper>
|
|
);
|
|
}
|