-
- {order.id}
-
+ {/* Header */}
+
+
+
+
+ #{order.order_number}
+
+
+ {statusConfig.text}
+
+
- {order.date}
-
-
-
- {order.time}
+ {formatDate.format(
+ order.created_at,
+ 'DD.MM.YYYY HH:mm',
+ )}
-
- {(order.total + order.deliveryFee).toLocaleString()}{' '}
- {"so'm"}
-
+
+
+ {formatPrice(
+ order.total_price + order.delivery_price,
+ true,
+ )}
+
+
+ {getPaymentTypeText(order.payment_type)}
+
+
-
- {order.items.map((item, i) => (
-
- ))}
-
- {order.items.map((i) => i.name).join(', ')}
-
+
+ {order.comment && (
+
+
+ Izoh:
+
+
{order.comment}
+
+ )}
+
+ {/* Total Price Breakdown */}
+
+
+
+ Mahsulotlar narxi:
+
+
+ {formatPrice(order.total_price, true)}
+
+
+
+ Yetkazish:
+
+ {formatPrice(order.delivery_price, true)}
+
+
+
+ Jami:
+
+ {formatPrice(
+ order.total_price + order.delivery_price,
+ true,
+ )}
+
+
-
+
+ {/* Actions */}
+
- ))}
+ );
+ })}
+
+
+
+
>
);
diff --git a/src/features/profile/ui/RefreshOrder.tsx b/src/features/profile/ui/RefreshOrder.tsx
new file mode 100644
index 0000000..ff9ad29
--- /dev/null
+++ b/src/features/profile/ui/RefreshOrder.tsx
@@ -0,0 +1,637 @@
+'use client';
+
+import { cart_api, OrderCreateBody } from '@/features/cart/lib/api';
+import { orderForm } from '@/features/cart/lib/form';
+import formatPhone from '@/shared/lib/formatPhone';
+import formatPrice from '@/shared/lib/formatPrice';
+import onlyNumber from '@/shared/lib/onlyNumber';
+import { Button } from '@/shared/ui/button';
+import {
+ Form,
+ FormControl,
+ FormField,
+ FormItem,
+ FormMessage,
+} from '@/shared/ui/form';
+import { Input } from '@/shared/ui/input';
+import { Label } from '@/shared/ui/label';
+import { Textarea } from '@/shared/ui/textarea';
+import { zodResolver } from '@hookform/resolvers/zod';
+import {
+ Map,
+ Placemark,
+ Polygon,
+ YMaps,
+ ZoomControl,
+} from '@pbe/react-yandex-maps';
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+import {
+ CheckCircle2,
+ Clock,
+ CreditCard,
+ Loader2,
+ LocateFixed,
+ MapPin,
+ Package,
+ Truck,
+ User,
+ Wallet,
+} from 'lucide-react';
+import { useTranslations } from 'next-intl';
+import Image from 'next/image';
+import { useEffect, useState } from 'react';
+import { useForm } from 'react-hook-form';
+import { toast } from 'sonner';
+import z from 'zod';
+import useOrderStore from '../lib/order';
+
+interface CoordsData {
+ lat: number;
+ lon: number;
+ polygon: [number, number][][];
+}
+
+const RefreshOrder = () => {
+ const { order: initialValues } = useOrderStore();
+ const t = useTranslations();
+ const queryClient = useQueryClient();
+
+ const initialCartItems = initialValues?.items.map((item) => ({
+ id: item.id,
+ product_id: item.product.id,
+ product_name: item.product.name,
+ product_price: item.price,
+ product_image:
+ item.product.image ||
+ item.product.images?.[0]?.image ||
+ '/placeholder.svg',
+ quantity: item.quantity,
+ }));
+
+ const cartItems = initialCartItems;
+
+ const form = useForm
>({
+ resolver: zodResolver(orderForm),
+ defaultValues: {
+ username: initialValues?.name,
+ comment: initialValues?.comment,
+ lat: '41.311081',
+ long: '69.240562',
+ phone: initialValues?.contact_number,
+ },
+ });
+
+ const [orderSuccess, setOrderSuccess] = useState(false);
+ const [paymentMethod, setPaymentMethod] = useState<'CASH' | 'ACCOUNT_NUMBER'>(
+ 'CASH',
+ );
+ const [deliveryMethod, setDeliveryMethod] = useState<
+ 'YandexGo' | 'DELIVERY_COURIES' | 'PICKUP'
+ >('DELIVERY_COURIES');
+
+ useEffect(() => {
+ if (initialValues) {
+ setPaymentMethod(initialValues.payment_type);
+ setDeliveryMethod(initialValues.delivery_type);
+ }
+ }, [initialValues]);
+
+ const subtotal = cartItems
+ ? cartItems.reduce(
+ (sum, item) => sum + item.product_price * item.quantity,
+ 0,
+ )
+ : 0;
+
+ const deliveryFee =
+ deliveryMethod === 'DELIVERY_COURIES'
+ ? subtotal > 50000
+ ? 0
+ : 15000
+ : deliveryMethod === 'YandexGo'
+ ? 25000
+ : 0;
+
+ const total = subtotal + deliveryFee;
+
+ const { mutate, isPending } = useMutation({
+ mutationFn: (body: OrderCreateBody) => cart_api.createOrder(body),
+ onSuccess: () => {
+ setOrderSuccess(true);
+ queryClient.refetchQueries({ queryKey: ['cart_items'] });
+ },
+ onError: () => {
+ toast.error('Xatolik yuz berdi', {
+ richColors: true,
+ position: 'top-center',
+ });
+ },
+ });
+
+ const [coords, setCoords] = useState({
+ latitude: 41.311081,
+ longitude: 69.240562,
+ zoom: 12,
+ });
+ const [polygonCoords, setPolygonCoords] = useState<
+ [number, number][][] | null
+ >(null);
+
+ const getCoords = async (name: string): Promise => {
+ const res = await fetch(
+ `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(
+ name,
+ )}&format=json&polygon_geojson=1&limit=1`,
+ );
+ const data = await res.json();
+ if (data.length > 0 && data[0].geojson) {
+ const lat = parseFloat(data[0].lat);
+ const lon = parseFloat(data[0].lon);
+ let polygon: [number, number][][] = [];
+ if (data[0].geojson.type === 'Polygon') {
+ polygon = data[0].geojson.coordinates.map((ring: [number, number][]) =>
+ ring.map((coord: [number, number]) => [coord[1], coord[0]]),
+ );
+ } else if (data[0].geojson.type === 'MultiPolygon') {
+ polygon = data[0].geojson.coordinates.map(
+ (poly: [number, number][][]) =>
+ poly[0].map((coord: [number, number]) => [coord[1], coord[0]]),
+ );
+ }
+ return { lat, lon, polygon };
+ }
+ return null;
+ };
+
+ const handleMapClick = (
+ e: ymaps.IEvent,
+ ) => {
+ const [lat, lon] = e.get('coords');
+ setCoords({ latitude: lat, longitude: lon, zoom: 18 });
+ form.setValue('lat', lat.toString(), { shouldDirty: true });
+ form.setValue('long', lon.toString(), { shouldDirty: true });
+ };
+
+ const handleShowMyLocation = () => {
+ if (!navigator.geolocation) {
+ alert('Sizning brauzeringiz geolokatsiyani qo‘llab-quvvatlamaydi');
+ return;
+ }
+ navigator.geolocation.getCurrentPosition(
+ (position) => {
+ const lat = position.coords.latitude;
+ const lon = position.coords.longitude;
+ setCoords({ latitude: lat, longitude: lon, zoom: 14 });
+ form.setValue('lat', lat.toString());
+ form.setValue('long', lon.toString());
+ },
+ (error) => {
+ alert('Joylashuv aniqlanmadi: ' + error.message);
+ },
+ );
+ };
+
+ const cityValue = form.watch('city');
+
+ useEffect(() => {
+ if (!cityValue || cityValue.length < 3) return;
+ const timeout = setTimeout(async () => {
+ const result = await getCoords(cityValue);
+ if (!result) return;
+ setCoords({
+ latitude: result.lat,
+ longitude: result.lon,
+ zoom: 12,
+ });
+ setPolygonCoords(result.polygon);
+ form.setValue('lat', result.lat.toString(), { shouldDirty: true });
+ form.setValue('long', result.lon.toString(), { shouldDirty: true });
+ }, 700);
+ return () => clearTimeout(timeout);
+ }, [cityValue]);
+
+ const onSubmit = (value: z.infer) => {
+ if (initialValues === null) {
+ toast.error('Savatcha bo‘sh', {
+ richColors: true,
+ position: 'top-center',
+ });
+ return;
+ }
+
+ const items = initialValues.items.map((item) => ({
+ product_id: item.product.id,
+ quantity: item.quantity,
+ }));
+
+ mutate({
+ comment: value.comment,
+ contact_number: onlyNumber(value.phone),
+ delivery_type: deliveryMethod,
+ name: value.username,
+ payment_type: paymentMethod,
+ items: items,
+ long: Number(value.long),
+ lat: Number(value.lat),
+ });
+ };
+
+ if (orderSuccess) {
+ return (
+
+
+
+
+
+
+ {t('Buyurtma qabul qilindi!')}
+
+
+ {t('Buyurtmangiz muvaffaqiyatli qabul qilindi')}
+
+
+
+
+ );
+ }
+
+ return (
+
+ <>
+ {/* Header */}
+
+
+ {t('Buyurtmani rasmiylashtirish')}
+
+
{t("Ma'lumotlaringizni to'ldiring")}
+
+
+
+ >
+
+ );
+};
+
+export default RefreshOrder;
diff --git a/src/shared/config/i18n/messages/ru.json b/src/shared/config/i18n/messages/ru.json
index c956ef4..35f0896 100644
--- a/src/shared/config/i18n/messages/ru.json
+++ b/src/shared/config/i18n/messages/ru.json
@@ -135,8 +135,8 @@
"Shaxsiy ma'lumotlar": "Личные данные",
"Ism": "Имя",
"Ismingiz": "Ваше имя",
- "Familiya": "Фамилия",
- "Familiyangiz": "Ваша фамилия",
+ "Familiya": "Имя Фамилия",
+ "Familiyangiz": "Ваше имя и фамилия",
"Telefon raqam": "Номер телефона",
"Izoh": "Комментарий",
"Yetkazib berish manzili": "Адрес доставки",
@@ -192,5 +192,5 @@
"So'rov yuborildi!": "Запрос успешно отправлен!",
"Tez-tez So'raladigan Savollar": "Часто задаваемые вопросы",
- "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar":"Ответы на самые часто задаваемые вопросы о Gastro Market"
+ "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar": "Ответы на самые часто задаваемые вопросы о Gastro Market"
}
diff --git a/src/shared/config/i18n/messages/uz.d.json.ts b/src/shared/config/i18n/messages/uz.d.json.ts
index 22fa21f..af3e082 100644
--- a/src/shared/config/i18n/messages/uz.d.json.ts
+++ b/src/shared/config/i18n/messages/uz.d.json.ts
@@ -140,8 +140,8 @@ declare const messages: {
"Shaxsiy ma'lumotlar": "Shaxsiy ma'lumotlar";
Ism: 'Ism';
Ismingiz: 'Ismingiz';
- Familiya: 'Familiya';
- Familiyangiz: 'Familiyangiz';
+ Familiya: 'Ism Familiya';
+ Familiyangiz: 'Ism Familiyangiz';
'Telefon raqam': 'Telefon raqam';
Izoh: 'Izoh';
'Yetkazib berish manzili': 'Yetkazib berish manzili';
diff --git a/src/shared/config/i18n/messages/uz.json b/src/shared/config/i18n/messages/uz.json
index 7e3d06e..9e422a9 100644
--- a/src/shared/config/i18n/messages/uz.json
+++ b/src/shared/config/i18n/messages/uz.json
@@ -137,8 +137,8 @@
"Shaxsiy ma'lumotlar": "Shaxsiy ma'lumotlar",
"Ism": "Ism",
"Ismingiz": "Ismingiz",
- "Familiya": "Familiya",
- "Familiyangiz": "Familiyangiz",
+ "Familiya": "Ism Familiya",
+ "Familiyangiz": "Ism Familiyangiz",
"Telefon raqam": "Telefon raqam",
"Izoh": "Izoh",
"Yetkazib berish manzili": "Yetkazib berish manzili",