- Chat list: auth-gated, shows all conversations for current user with other participant's avatar/name, last message preview, and relative time in Macedonian (пред X мин/ч/д) - Chat conversation: FlatList with inverted scroll, message bubbles aligned left (other) and right (self), colored backgrounds, timestamps, KeyboardAvoidingView send bar - Chat mutations: getOrCreate finds or creates a 1:1 chat, send creates message and updates lastMessageAt - Message queries: listByChat with participant auth check - Wired ad detail 'Започни разговор' button to create/open chat - ChatListItem component with avatar, preview, time, link to detail All UI text in Macedonian. TypeScript clean, Convex functions deployed.
123 lines
3.3 KiB
TypeScript
123 lines
3.3 KiB
TypeScript
import { View, Text, ScrollView } from "react-native";
|
||
import { useRouter } from "expo-router";
|
||
import { useQuery } from "convex/react";
|
||
import { api } from "../../../convex/_generated/api";
|
||
import { useAuth } from "../../_layout";
|
||
import { useTheme } from "../../../components/theme";
|
||
import { ChatListItem } from "../../../components/chat-list-item";
|
||
import { Button } from "../../../components/ui/button";
|
||
import { Loading } from "../../../components/ui/loading";
|
||
|
||
export default function ChatScreen() {
|
||
const theme = useTheme();
|
||
const router = useRouter();
|
||
const { token, userId, isAuthenticated } = useAuth();
|
||
|
||
const chats = useQuery(
|
||
api.chats.listByUser,
|
||
isAuthenticated && token ? { token } : "skip"
|
||
);
|
||
|
||
if (!isAuthenticated) {
|
||
return (
|
||
<ScrollView
|
||
contentInsetAdjustmentBehavior="automatic"
|
||
contentContainerStyle={{ padding: theme.spacing.lg }}
|
||
>
|
||
<View
|
||
style={{
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
paddingVertical: 60,
|
||
}}
|
||
>
|
||
<Text style={{ fontSize: 48, marginBottom: 16 }}>
|
||
{"\uD83D\uDCAC"}
|
||
</Text>
|
||
<Text
|
||
style={{
|
||
fontSize: 18,
|
||
fontWeight: "600",
|
||
color: theme.colors.text,
|
||
marginBottom: 8,
|
||
}}
|
||
>
|
||
Чатови
|
||
</Text>
|
||
<Text
|
||
style={{
|
||
color: theme.colors.textSecondary,
|
||
textAlign: "center",
|
||
marginBottom: 24,
|
||
}}
|
||
>
|
||
Најавете се за да ги видите вашите разговори.
|
||
</Text>
|
||
<Button onPress={() => router.push("/(auth)/login")}>
|
||
Најави се
|
||
</Button>
|
||
</View>
|
||
</ScrollView>
|
||
);
|
||
}
|
||
|
||
if (chats === undefined) {
|
||
return (
|
||
<View
|
||
style={{
|
||
flex: 1,
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
backgroundColor: theme.colors.background,
|
||
}}
|
||
>
|
||
<Loading />
|
||
</View>
|
||
);
|
||
}
|
||
|
||
if (chats.length === 0) {
|
||
return (
|
||
<ScrollView
|
||
contentInsetAdjustmentBehavior="automatic"
|
||
contentContainerStyle={{ padding: theme.spacing.lg }}
|
||
>
|
||
<View
|
||
style={{
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
paddingVertical: 60,
|
||
}}
|
||
>
|
||
<Text style={{ fontSize: 48, marginBottom: 16 }}>
|
||
{"\uD83D\uDCAC"}
|
||
</Text>
|
||
<Text
|
||
style={{
|
||
fontSize: 18,
|
||
fontWeight: "600",
|
||
color: theme.colors.text,
|
||
marginBottom: 8,
|
||
}}
|
||
>
|
||
Немате разговори
|
||
</Text>
|
||
<Text style={{ color: theme.colors.textSecondary, textAlign: "center" }}>
|
||
Започнете разговор со мајстор или клиент.
|
||
</Text>
|
||
</View>
|
||
</ScrollView>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<ScrollView
|
||
contentInsetAdjustmentBehavior="automatic"
|
||
style={{ backgroundColor: theme.colors.background }}
|
||
>
|
||
{chats.map((chat) => (
|
||
<ChatListItem key={chat._id} chat={chat} currentUserId={userId!} />
|
||
))}
|
||
</ScrollView>
|
||
);
|
||
} |