api ulandi
This commit is contained in:
@@ -1,264 +1,34 @@
|
||||
'use client';
|
||||
|
||||
import { PartnershipForm } from '@/features/about/ui/AboutPage';
|
||||
import Faq from '@/features/faq/ui/Faq';
|
||||
import Favourite from '@/features/favourite/ui/Favourite';
|
||||
import { useRouter } from '@/shared/config/i18n/navigation';
|
||||
import { getMe, removeToken } from '@/shared/lib/token';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/shared/ui/avatar';
|
||||
import { Badge } from '@/shared/ui/badge';
|
||||
import { Button } from '@/shared/ui/button';
|
||||
import { Card, CardContent } from '@/shared/ui/card';
|
||||
import {
|
||||
CheckCircle,
|
||||
ChevronRight,
|
||||
History,
|
||||
Home,
|
||||
LogOut,
|
||||
MapPin,
|
||||
Package,
|
||||
RefreshCw,
|
||||
ShoppingBag,
|
||||
Truck,
|
||||
} from 'lucide-react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { Headset, Home, LogOut } from 'lucide-react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useState } from 'react';
|
||||
import { orders, user } from '../lib/data';
|
||||
import HistoryTabs from './History';
|
||||
import Orders from './Orders';
|
||||
import CustomerSupport from './Support';
|
||||
|
||||
const Profile = () => {
|
||||
const [activeSection, setActiveSection] = useState('overview');
|
||||
const router = useRouter();
|
||||
|
||||
const getStatusInfo = (status: string) => {
|
||||
const statusMap: Record<
|
||||
string,
|
||||
{ text: string; color: string; bgColor: string }
|
||||
> = {
|
||||
inTransit: {
|
||||
text: "Yo'lda",
|
||||
color: 'text-blue-600',
|
||||
bgColor: 'bg-blue-100',
|
||||
},
|
||||
atPickup: {
|
||||
text: 'Punktda',
|
||||
color: 'text-amber-600',
|
||||
bgColor: 'bg-amber-100',
|
||||
},
|
||||
delivered: {
|
||||
text: 'Yetkazildi',
|
||||
color: 'text-emerald-600',
|
||||
bgColor: 'bg-emerald-100',
|
||||
},
|
||||
cancelled: {
|
||||
text: 'Bekor qilindi',
|
||||
color: 'text-red-600',
|
||||
bgColor: 'bg-red-100',
|
||||
},
|
||||
};
|
||||
return (
|
||||
statusMap[status] || {
|
||||
text: status,
|
||||
color: 'text-muted-foreground',
|
||||
bgColor: 'bg-muted',
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case 'inTransit':
|
||||
return <Truck className="w-4 h-4" />;
|
||||
case 'atPickup':
|
||||
return <MapPin className="w-4 h-4" />;
|
||||
case 'delivered':
|
||||
return <CheckCircle className="w-4 h-4" />;
|
||||
default:
|
||||
return <Package className="w-4 h-4" />;
|
||||
}
|
||||
};
|
||||
const t = useTranslations();
|
||||
const queryClient = useQueryClient();
|
||||
const user = getMe();
|
||||
|
||||
const menuItems = [
|
||||
{ id: 'overview', label: 'Umumiy', icon: Home },
|
||||
{ id: 'orders', label: 'Buyurtmalar', icon: ShoppingBag },
|
||||
{ id: 'history', label: 'Tarix', icon: History },
|
||||
{ id: 'support', label: "Qo'llab-quvatlash", icon: Headset },
|
||||
];
|
||||
|
||||
const renderContent = () => {
|
||||
switch (activeSection) {
|
||||
case 'orders':
|
||||
return <Orders />;
|
||||
|
||||
case 'history':
|
||||
return <HistoryTabs />;
|
||||
|
||||
case 'favorites':
|
||||
return <Favourite />;
|
||||
|
||||
case 'agency':
|
||||
return <PartnershipForm />;
|
||||
|
||||
case 'faq':
|
||||
return <Faq />;
|
||||
case 'support':
|
||||
return <CustomerSupport />;
|
||||
router.push('https://t.me/web_app_0515_bot');
|
||||
|
||||
default:
|
||||
return (
|
||||
<>
|
||||
{/* Active Orders Section */}
|
||||
<div className="mb-6 md:mb-8">
|
||||
<div className="flex items-center justify-between mb-3 md:mb-4">
|
||||
<h3 className="text-base md:text-lg font-semibold text-foreground">
|
||||
Faol buyurtmalar
|
||||
</h3>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-emerald-600 hover:text-emerald-700 h-8 text-xs md:text-sm"
|
||||
onClick={() => setActiveSection('orders')}
|
||||
>
|
||||
Barchasi
|
||||
<ChevronRight className="w-3 h-3 md:w-4 md:h-4 ml-1" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{orders
|
||||
.filter((o) => o.status !== 'delivered')
|
||||
.slice(0, 2)
|
||||
.map((order) => {
|
||||
const statusInfo = getStatusInfo(order.status);
|
||||
return (
|
||||
<Card
|
||||
key={order.id}
|
||||
className="border-0 shadow-sm hover:shadow-md transition-shadow"
|
||||
>
|
||||
<CardContent className="p-3 md:p-5">
|
||||
<div className="flex items-start justify-between mb-3 md:mb-4">
|
||||
<div className="flex items-center gap-2 md:gap-3">
|
||||
<div
|
||||
className={`w-10 h-10 md:w-12 md:h-12 rounded-xl ${statusInfo.bgColor} flex items-center justify-center shrink-0`}
|
||||
>
|
||||
<span className={statusInfo.color}>
|
||||
{getStatusIcon(order.status)}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-semibold text-sm md:text-base text-foreground">
|
||||
{order.id}
|
||||
</p>
|
||||
<p className="text-xs md:text-sm text-muted-foreground">
|
||||
{order.date} • {order.time}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Badge
|
||||
className={`${statusInfo.bgColor} ${statusInfo.color} border-0 text-xs`}
|
||||
>
|
||||
{statusInfo.text}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-1.5 md:gap-2 mb-3 md:mb-4">
|
||||
{order.items.map((item, idx) => (
|
||||
<span
|
||||
key={idx}
|
||||
className="px-2 md:px-3 py-1 bg-slate-100 rounded-full text-xs text-muted-foreground"
|
||||
>
|
||||
{item.name} ×{item.quantity}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between pt-3 md:pt-4 border-t border-slate-100 gap-2">
|
||||
<div className="flex items-center gap-2 text-xs md:text-sm text-muted-foreground">
|
||||
<MapPin className="w-3 h-3 md:w-4 md:h-4 shrink-0" />
|
||||
<span className="truncate">{order.address}</span>
|
||||
</div>
|
||||
<p className="font-bold text-sm md:text-base text-foreground">
|
||||
{(
|
||||
order.total + order.deliveryFee
|
||||
).toLocaleString()}{' '}
|
||||
{"so'm"}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Order History */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-3 md:mb-4">
|
||||
<h3 className="text-base md:text-lg font-semibold text-foreground">
|
||||
Buyurtmalar tarixi
|
||||
</h3>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-emerald-600 hover:text-emerald-700 h-8 text-xs md:text-sm"
|
||||
onClick={() => setActiveSection('history')}
|
||||
>
|
||||
Barchasi{' '}
|
||||
<ChevronRight className="w-3 h-3 md:w-4 md:h-4 ml-1" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
{orders
|
||||
.filter((o) => o.status === 'delivered')
|
||||
.slice(0, 2)
|
||||
.map((order) => (
|
||||
<Card
|
||||
key={order.id}
|
||||
className="border-0 shadow-sm hover:shadow-md transition-shadow"
|
||||
>
|
||||
<CardContent className="p-3 md:p-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3 md:gap-4">
|
||||
<div className="w-10 h-10 md:w-12 md:h-12 rounded-xl bg-emerald-100 flex items-center justify-center shrink-0">
|
||||
<CheckCircle className="w-4 h-4 md:w-5 md:h-5 text-emerald-600" />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p className="font-semibold text-sm md:text-base text-foreground">
|
||||
{order.id}
|
||||
</p>
|
||||
<p className="text-xs md:text-sm text-muted-foreground truncate">
|
||||
{order.items.map((i) => i.name).join(', ')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right shrink-0 ml-2">
|
||||
<p className="font-bold text-sm md:text-base text-foreground">
|
||||
{(
|
||||
order.total + order.deliveryFee
|
||||
).toLocaleString()}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{order.date}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2 mt-3 md:mt-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="flex-1 gap-1 md:gap-2 bg-transparent h-8 md:h-9 text-xs md:text-sm"
|
||||
>
|
||||
<RefreshCw className="w-3 h-3 md:w-4 md:h-4" />
|
||||
Qayta
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
return <HistoryTabs />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -279,7 +49,7 @@ const Profile = () => {
|
||||
}`}
|
||||
>
|
||||
<Icon className="w-4 h-4" />
|
||||
{item.label}
|
||||
{t(item.label)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
@@ -289,20 +59,18 @@ const Profile = () => {
|
||||
<div>
|
||||
<div className="flex gap-4 md:gap-6">
|
||||
{/* Desktop Sidebar - hidden on mobile */}
|
||||
<div className="hidden md:block w-80 shrink-0">
|
||||
<div className="hidden lg:block w-80 shrink-0">
|
||||
<div className="flex items-center gap-4 mb-8">
|
||||
<Avatar className="w-14 h-14 ring-2 ring-emerald-500 ring-offset-2 flex items-center justify-center">
|
||||
<AvatarImage
|
||||
src={user.avatar || '/placeholder.svg'}
|
||||
alt={user.phone}
|
||||
className="h-12 w-12"
|
||||
/>
|
||||
<AvatarFallback className="bg-emerald-500 text-white font-semibold">
|
||||
U
|
||||
<AvatarImage />
|
||||
<AvatarFallback className="text-muted-foreground font-semibold">
|
||||
{user?.slice(0, 1).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div>
|
||||
<p className="text-sm text-muted-foreground">{user.phone}</p>
|
||||
<p className="text-lg text-muted-foreground font-medium">
|
||||
{user && user.charAt(0).toUpperCase() + user.slice(1)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -319,7 +87,7 @@ const Profile = () => {
|
||||
}`}
|
||||
>
|
||||
<item.icon className="w-5 h-5" />
|
||||
{item.label}
|
||||
{t(item.label)}
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
@@ -328,13 +96,16 @@ const Profile = () => {
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
localStorage.removeItem('user');
|
||||
queryClient.refetchQueries({ queryKey: ['product_list'] });
|
||||
queryClient.refetchQueries({ queryKey: ['favourite_product'] });
|
||||
queryClient.refetchQueries({ queryKey: ['search'] });
|
||||
removeToken();
|
||||
router.push('/');
|
||||
}}
|
||||
className="w-full justify-start gap-3 text-red-500 hover:text-red-600 hover:bg-red-50 mt-4"
|
||||
>
|
||||
<LogOut className="w-5 h-5" />
|
||||
Chiqish
|
||||
{t('Chiqish')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -343,17 +114,14 @@ const Profile = () => {
|
||||
<div className="lg:hidden flex items-center justify-between mb-4 md:mb-6">
|
||||
<div className="flex items-center gap-2 md:gap-3">
|
||||
<Avatar className="w-10 h-10 md:w-12 md:h-12 ring-2 ring-emerald-500 ring-offset-2">
|
||||
<AvatarImage
|
||||
src={user.avatar || '/placeholder.svg'}
|
||||
alt={user.phone}
|
||||
/>
|
||||
<AvatarFallback className="bg-emerald-500 text-white text-sm md:text-base">
|
||||
U
|
||||
<AvatarImage />
|
||||
<AvatarFallback className="text-muted-foreground font-semibold">
|
||||
{user?.slice(0, 1).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div>
|
||||
<p className="text-xs md:text-sm text-muted-foreground">
|
||||
{user.phone}
|
||||
<p className="text-md md:text-xl text-muted-foreground">
|
||||
{user && user.charAt(0).toUpperCase() + user.slice(1)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -361,7 +129,12 @@ const Profile = () => {
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => {
|
||||
localStorage.removeItem('user');
|
||||
queryClient.refetchQueries({ queryKey: ['product_list'] });
|
||||
queryClient.refetchQueries({
|
||||
queryKey: ['favourite_product'],
|
||||
});
|
||||
queryClient.refetchQueries({ queryKey: ['search'] });
|
||||
removeToken();
|
||||
router.push('/');
|
||||
}}
|
||||
className="w-9 h-9 md:w-10 md:h-10"
|
||||
|
||||
Reference in New Issue
Block a user