mojmajstor/app/(tabs)/(posts)/index.tsx
2026-06-04 20:37:09 +02:00

140 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { View, Text, ScrollView, RefreshControl, Pressable } from "react-native";
import { useRouter } from "expo-router";
import { useState, useCallback } from "react";
import { usePaginatedQuery, useQuery } from "convex/react";
import { api } from "../../../convex/_generated/api";
import { useAuth } from "../../_layout";
import { useTheme } from "../../../components/theme";
import { PostCard } from "../../../components/post-card";
import { Loading } from "../../../components/ui/loading";
import { Button } from "../../../components/ui/button";
const TABS = [
{ key: "open", label: "Отворени" },
{ key: "all", label: "Сите" },
] as const;
type TabKey = (typeof TABS)[number]["key"];
export default function PostsScreen() {
const router = useRouter();
const theme = useTheme();
const { token, isAuthenticated } = useAuth();
const currentUser = useQuery(
api.users.getCurrentUser,
isAuthenticated && token ? { token } : "skip"
);
const [activeTab, setActiveTab] = useState<TabKey>("open");
const [refreshing, setRefreshing] = useState(false);
const postsResult = usePaginatedQuery(
api.posts.listPaginated,
activeTab === "open" ? { status: "open" as const } : {},
{ initialNumItems: 20 }
);
const onRefresh = useCallback(() => {
setRefreshing(true);
setTimeout(() => setRefreshing(false), 800);
}, []);
const isCustomer = currentUser?.role !== "handyman";
return (
<ScrollView
contentInsetAdjustmentBehavior="automatic"
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} tintColor={theme.colors.primary} />
}
contentContainerStyle={{ padding: theme.spacing.lg, gap: theme.spacing.md, paddingBottom: 80 }}
>
{isAuthenticated && isCustomer && (
<Button
onPress={() => router.push("/post/create" as any)}
size="lg"
accessibilityLabel="Креирај ново побарување"
>
+ Ново побарување
</Button>
)}
<View style={{
flexDirection: "row",
backgroundColor: theme.colors.surfaceAlt,
borderRadius: theme.radius.md,
padding: 3,
}}>
{TABS.map((tab) => (
<Pressable
key={tab.key}
accessible
accessibilityLabel={`Прикажи ${tab.label.toLowerCase()} побарувања`}
accessibilityRole="button"
accessibilityState={{ selected: activeTab === tab.key }}
onPress={() => setActiveTab(tab.key)}
style={{
flex: 1,
paddingVertical: 10,
borderRadius: theme.radius.sm,
alignItems: "center",
backgroundColor: activeTab === tab.key ? theme.colors.card : "transparent",
...(activeTab === tab.key ? theme.shadows.sm : undefined),
}}
>
<Text
style={{
fontWeight: activeTab === tab.key ? "600" : "400",
fontSize: 14,
color: activeTab === tab.key ? theme.colors.text : theme.colors.textSecondary,
}}
>
{tab.label}
</Text>
</Pressable>
))}
</View>
{postsResult.status === "LoadingFirstPage" ? (
<Loading />
) : postsResult.results.length === 0 ? (
<View style={{ alignItems: "center", paddingVertical: 60 }}>
<Text style={{ fontSize: 48, marginBottom: theme.spacing.md }}>📋</Text>
<Text style={{ ...theme.typography.h3, color: theme.colors.text, marginBottom: theme.spacing.sm }}>
Нема побарувања
</Text>
<Text style={{ ...theme.typography.body, color: theme.colors.textSecondary, textAlign: "center" }}>
{activeTab === "open"
? "Нема отворени побарувања во моментот."
: "Сè уште нема побарувања."}
</Text>
</View>
) : (
<View style={{ gap: theme.spacing.md }}>
{postsResult.results.map((post) => (
<PostCard key={post._id} post={post} />
))}
</View>
)}
{postsResult.status === "CanLoadMore" && (
<Pressable
accessible
accessibilityLabel="Вчитај повеќе побарувања"
accessibilityRole="button"
onPress={() => postsResult.loadMore(20)}
style={{
backgroundColor: theme.colors.surfaceAlt,
borderRadius: theme.radius.md,
paddingVertical: theme.spacing.md,
alignItems: "center",
borderWidth: 1,
borderColor: theme.colors.borderLight,
}}
>
<Text style={{ color: theme.colors.primary, fontWeight: "600", fontSize: 15 }}>Вчитај повеќе</Text>
</Pressable>
)}
</ScrollView>
);
}