freshyo/apps/user-ui/app/(drawer)/(tabs)/me/complaints/index.tsx
2026-01-24 00:13:15 +05:30

187 lines
No EOL
7.1 KiB
TypeScript

import React from 'react';
import { View, Linking, TouchableOpacity, ActivityIndicator } from 'react-native';
import { Image } from 'expo-image';
import { MyText, tw, useManualRefresh, MyFlatList, useMarkDataFetchers, theme, MyTouchableOpacity } from 'common-ui';
import { MaterialIcons, Ionicons } from '@expo/vector-icons';
import { trpc } from '@/src/trpc-client';
import { useGetEssentialConsts } from '@/src/api-hooks/essential-consts.api';
import dayjs from 'dayjs';
import { useRouter } from 'expo-router';
interface ComplaintItemProps {
item: any;
}
const ComplaintItem: React.FC<ComplaintItemProps> = ({ item }) => (
<View style={tw`bg-white rounded-2xl p-5 mb-4 shadow-sm border border-gray-100`}>
{/* Header: ID, Date, Status */}
<View style={tw`flex-row justify-between items-start mb-3`}>
<View>
<View style={tw`flex-row items-center`}>
<MyText style={tw`text-base font-bold text-gray-900`}>
Complaint #{item.id}
</MyText>
{item.orderId && (
<View style={tw`bg-gray-100 px-2 py-0.5 rounded ml-2`}>
<MyText style={tw`text-[10px] font-bold text-gray-500`}>
Order #{item.orderId}
</MyText>
</View>
)}
</View>
<MyText style={tw`text-xs text-gray-400 mt-1`}>
{dayjs(item.createdAt).format('MMM DD, YYYY • h:mm A')}
</MyText>
</View>
<View style={tw`px-3 py-1 rounded-full ${item.isResolved ? 'bg-green-100' : 'bg-amber-100'
}`}>
<MyText style={tw`text-xs font-bold ${item.isResolved ? 'text-green-700' : 'text-amber-700'
}`}>
{item.isResolved ? 'Resolved' : 'Pending'}
</MyText>
</View>
</View>
{/* Complaint Body */}
<MyText style={tw`text-gray-700 text-sm leading-6 mb-4`}>
{item.complaintBody}
</MyText>
{/* Admin Response */}
{item.response && (
<View style={tw`bg-blue-50 p-4 rounded-xl border border-blue-100`}>
<View style={tw`flex-row items-center mb-2`}>
<View style={tw`w-6 h-6 bg-blue-100 rounded-full items-center justify-center mr-2`}>
<MaterialIcons name="support-agent" size={14} color="#2563EB" />
</View>
<MyText style={tw`text-xs font-bold text-blue-800 uppercase tracking-wide`}>
Support Response
</MyText>
</View>
<MyText style={tw`text-sm text-blue-900 leading-5`}>
{item.response}
</MyText>
</View>
)}
{!item.response && !item.isResolved && (
<View style={tw`flex-row items-center mt-2`}>
<MaterialIcons name="schedule" size={14} color="#9CA3AF" />
<MyText style={tw`text-xs text-gray-400 ml-1 italic`}>
We are reviewing your complaint...
</MyText>
</View>
)}
</View>
);
export default function Complaints() {
const router = useRouter();
const { data, isLoading, error, refetch } = trpc.user.complaint.getAll.useQuery();
const complaints = data?.complaints || [];
const { data: constsData } = useGetEssentialConsts();
useManualRefresh(() => refetch());
useMarkDataFetchers(() => {
refetch();
});
if (isLoading) {
return (
<View style={tw`flex-1 justify-center items-center bg-gray-50`}>
<MyText style={tw`text-gray-500 font-medium`}>Loading complaints...</MyText>
</View>
);
}
if (error) {
return (
<View style={tw`flex-1 justify-center items-center bg-gray-50`}>
<MaterialIcons name="error-outline" size={48} color="#EF4444" />
<MyText style={tw`text-gray-900 text-lg font-bold mt-4`}>Oops!</MyText>
<MyText style={tw`text-gray-500 mt-2`}>Failed to load complaints</MyText>
</View>
);
}
return (
<View style={tw`flex-1 bg-gray-50`}>
<MyFlatList
data={complaints}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => <ComplaintItem item={item} />}
contentContainerStyle={tw`px-4 py-6`}
ListHeaderComponent={
<View style={tw`bg-brand500 px-4 py-5`}>
<View style={tw`flex-row items-center mb-4`}>
<View style={tw`w-10 h-10 bg-white/20 rounded-full items-center justify-center mr-3`}>
<MaterialIcons name="support-agent" size={22} color="white" />
</View>
<MyText style={tw`text-lg font-bold text-white`}>Need Help?</MyText>
</View>
<View style={tw`flex-col`}>
<TouchableOpacity
style={tw`w-full bg-white rounded-xl p-3 mb-3 flex-row items-center`}
onPress={() => {
const phone = constsData?.supportMobile || '8688182552';
Linking.openURL(`tel:${phone}`);
}}
>
<View style={tw`w-10 h-10 bg-green-100 rounded-full items-center justify-center mr-3`}>
<Ionicons name="call" size={20} color="#16A34A" />
</View>
<View>
<MyText style={tw`text-[10px] text-gray-500 uppercase font-bold`}>Call Us</MyText>
<MyText style={tw`text-base font-bold text-gray-900`}>
{constsData?.supportMobile || '8688182552'}
</MyText>
</View>
</TouchableOpacity>
<TouchableOpacity
style={tw`w-full bg-white rounded-xl p-3 flex-row items-center`}
onPress={() => {
const email = constsData?.supportEmail || 'qushammohd@gmail.com';
Linking.openURL(`mailto:${email}`);
}}
>
<View style={tw`w-10 h-10 bg-blue-100 rounded-full items-center justify-center mr-3`}>
<MaterialIcons name="email" size={20} color="#2563EB" />
</View>
<View>
<MyText style={tw`text-[10px] text-gray-500 uppercase font-bold`}>Email</MyText>
<MyText style={tw`text-sm font-bold text-gray-900`} numberOfLines={1}>
{constsData?.supportEmail || 'qushammohd@gmail.com'}
</MyText>
</View>
</TouchableOpacity>
</View>
</View>
}
ListEmptyComponent={
<View style={tw`flex-1 justify-center items-center py-20`}>
<View style={tw`w-20 h-20 bg-gray-100 rounded-full items-center justify-center mb-6`}>
<MaterialIcons name="thumb-up-off-alt" size={40} color="#9CA3AF" />
</View>
<MyText style={tw`text-xl font-bold text-gray-900`}>No Complaints</MyText>
<MyText style={tw`text-gray-500 text-center mt-2 px-10 leading-5`}>
You haven&apos;t raised any complaints yet. That&apos;s great!
</MyText>
<MyTouchableOpacity
onPress={() => router.push('/(drawer)/(tabs)/home')}
style={tw`mt-8 bg-brand500 px-6 py-3 rounded-xl shadow-sm`}
>
<MyText style={tw`text-white font-bold`}>Continue Shopping</MyText>
</MyTouchableOpacity>
</View>
}
/>
</View>
);
}