From 2d96eab3d7f25d2d733ce532889613c3d713ea20 Mon Sep 17 00:00:00 2001 From: Samandar Turgunboyev Date: Tue, 4 Nov 2025 18:10:37 +0500 Subject: [PATCH] post bug fix --- .env | 2 +- src/pages/news/lib/data.ts | 6 +- src/pages/news/lib/form.ts | 22 ++- src/pages/news/lib/type.ts | 8 +- src/pages/news/ui/AddNews.tsx | 21 +- src/pages/news/ui/News.tsx | 101 ++++++++-- src/pages/news/ui/StepOne.tsx | 168 +++++++++------- src/pages/news/ui/StepTwo.tsx | 179 ++++++++++-------- .../config/i18n/locales/ru/translation.json | 5 +- .../config/i18n/locales/uz/translation.json | 5 +- 10 files changed, 325 insertions(+), 192 deletions(-) diff --git a/.env b/.env index 5dea892..37f214b 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -VITE_API_URL=https://simple-travel.felixits.uz/api/v1/ \ No newline at end of file +VITE_API_URL=https://api.simpletravel.uz/api/v1/ \ No newline at end of file diff --git a/src/pages/news/lib/data.ts b/src/pages/news/lib/data.ts index 4fb5d27..d2f9b22 100644 --- a/src/pages/news/lib/data.ts +++ b/src/pages/news/lib/data.ts @@ -6,7 +6,7 @@ interface NewsData { desc: string; title_ru: string; desc_ru: string; - category: string; + category: number | null; banner: File | undefined | string; } @@ -20,7 +20,7 @@ export const useNewsStore = create((set) => ({ stepOneData: { title: "", desc: "", - category: "", + category: null, banner: undefined, desc_ru: "", title_ru: "", @@ -31,7 +31,7 @@ export const useNewsStore = create((set) => ({ stepOneData: { title: "", desc: "", - category: "", + category: null, banner: undefined, desc_ru: "", title_ru: "", diff --git a/src/pages/news/lib/form.ts b/src/pages/news/lib/form.ts index 2198ab4..2314a22 100644 --- a/src/pages/news/lib/form.ts +++ b/src/pages/news/lib/form.ts @@ -18,12 +18,13 @@ export const newsForm = z.object({ desc_ru: z.string().min(2, { message: "Kamida 2 ta belgidan iborat bo‘lishi kerak.", }), - category: z.string().min(1, { + category: z.number().min(1, { message: "Majburiy maydon", }), banner: fileSchema, }); +// zod schema ni yangilaymiz export const newsPostForm = z.object({ desc: z .string() @@ -36,17 +37,22 @@ export const newsPostForm = z.object({ sections: z .array( z.object({ - image: fileSchema, - text: z.string().min(1, { message: "Matn bo'sh bo'lmasligi kerak." }), - text_ru: z - .string() - .min(1, { message: "Ruscha matn bo'sh bo'lmasligi kerak." }), + image: z.union([z.instanceof(File), z.string()]).optional(), + text: z.string().optional(), + text_ru: z.string().optional(), }), ) - .min(1, { message: "Kamida bitta bo‘lim qo‘shing." }), + .optional(), post_tags: z - .array(z.string().min(1, { message: "Teg bo'sh bo'lmasligi kerak." })) + .array( + z.object({ + name: z.string().min(1, { message: "Teg bo'sh bo'lmasligi kerak." }), + name_ru: z + .string() + .min(1, { message: "Teg (RU) bo'sh bo'lmasligi kerak." }), + }), + ) .min(1, { message: "Kamida bitta teg kiriting." }), }); diff --git a/src/pages/news/lib/type.ts b/src/pages/news/lib/type.ts index 0ac1d0b..cf071fb 100644 --- a/src/pages/news/lib/type.ts +++ b/src/pages/news/lib/type.ts @@ -98,12 +98,8 @@ export interface NewsDetail { text_ru: string; text_uz: string; is_public: boolean; - category: { - name: string; - name_ru: string; - name_uz: string; - }; - tag: [ + category: { id: number; name: string; name_ru: string; name_uz: string }; + post_tags: [ { id: number; name: string; diff --git a/src/pages/news/ui/AddNews.tsx b/src/pages/news/ui/AddNews.tsx index b95edc2..cf656b4 100644 --- a/src/pages/news/ui/AddNews.tsx +++ b/src/pages/news/ui/AddNews.tsx @@ -4,7 +4,7 @@ import StepOne from "@/pages/news/ui/StepOne"; import StepTwo from "@/pages/news/ui/StepTwo"; import { useQuery } from "@tanstack/react-query"; -import { useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { useParams } from "react-router-dom"; @@ -13,7 +13,7 @@ const AddNews = () => { const isEditMode = useMemo(() => !!id, [id]); const [step, setStep] = useState(1); const { t } = useTranslation(); - const { data } = useQuery({ + const { data, refetch } = useQuery({ queryKey: ["news_detail", id], queryFn: () => getDetailNews(Number(id)), select(data) { @@ -22,6 +22,12 @@ const AddNews = () => { enabled: !!id, }); + useEffect(() => { + if (id) { + refetch(); + } + }, [id]); + return (

@@ -41,9 +47,16 @@ const AddNews = () => {

{step === 1 && ( - + + )} + {step === 2 && ( + )} - {step === 2 && } ); }; diff --git a/src/pages/news/ui/News.tsx b/src/pages/news/ui/News.tsx index 53ffab5..7185720 100644 --- a/src/pages/news/ui/News.tsx +++ b/src/pages/news/ui/News.tsx @@ -1,5 +1,5 @@ "use client"; -import { deleteNews, getAllNews } from "@/pages/news/lib/api"; +import { deleteNews, getAllNews, updateNews } from "@/pages/news/lib/api"; import { Badge } from "@/shared/ui/badge"; import { Button } from "@/shared/ui/button"; import { Card } from "@/shared/ui/card"; @@ -10,12 +10,15 @@ import { DialogHeader, DialogTitle, } from "@/shared/ui/dialog"; +import { Switch } from "@/shared/ui/switch"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import clsx from "clsx"; import { ChevronLeft, ChevronRight, Edit, + Eye, + EyeOff, FolderOpen, Loader2, PlusCircle, @@ -41,11 +44,33 @@ const News = () => { queryFn: () => getAllNews({ page: currentPage, page_size: 10 }), }); - const { mutate, isPending } = useMutation({ + const { mutate: deleteMutate, isPending } = useMutation({ mutationFn: (id: number) => deleteNews(id), onSuccess: () => { setDeleteId(null); queryClient.refetchQueries({ queryKey: ["all_news"] }); + toast.success(t("Yangilik o'chirildi"), { + richColors: true, + position: "top-center", + }); + }, + onError: () => { + toast.error(t("Xatolik yuz berdi"), { + richColors: true, + position: "top-center", + }); + }, + }); + + const { mutate: togglePublicMutate } = useMutation({ + mutationFn: ({ id, body }: { id: number; body: FormData }) => + updateNews({ body, id }), + onSuccess: () => { + queryClient.refetchQueries({ queryKey: ["all_news"] }); + toast.success(t("Status o'zgartirildi"), { + richColors: true, + position: "top-center", + }); }, onError: () => { toast.error(t("Xatolik yuz berdi"), { @@ -57,10 +82,21 @@ const News = () => { const confirmDelete = () => { if (deleteId) { - mutate(deleteId); + deleteMutate(deleteId); } }; + const handleTogglePublic = (id: number, currentStatus: boolean) => { + const formData = new FormData(); + console.log(currentStatus); + + formData.append("is_public", String(currentStatus)); + togglePublicMutate({ + id, + body: formData, + }); + }; + if (isLoading) { return (
@@ -135,10 +171,10 @@ const News = () => { allNews?.data.data.results.map((item) => ( {/* Image */} -
+
{item.title} {
{/* Content */} -
+
{/* Title */}

{item.title} @@ -169,21 +205,47 @@ const News = () => { {item.text}

- {/* Date */} -
- {item.is_public} -
- {/* Slug */} -
- {item.tag?.map((e) => ( - - /{e.name} - - ))} + {item.tag && item.tag.length > 0 && ( +
+ {item.tag.map((e, idx) => ( + + /{e.name} + + ))} +
+ )} + + {/* Spacer to push content to bottom */} +
+ + {/* Public/Private Toggle */} +
+
+
+ {item.is_public ? ( + + ) : ( + + )} + + {t("Оmmaviy")} + +
+ + handleTogglePublic(item.id, !item.is_public) + } + className="data-[state=checked]:bg-green-600" + /> +
- {/* Actions */} + {/* Actions - at the very bottom */}
- )} + {tagFields.map((field, i) => ( +
+ ( + - + -
- + + )} + /> + ( + + + + + + + )} + /> + {tagFields.length > 1 && ( + )} - /> +
))}
- {fields.map((field, index) => ( + {/* Sections */} + {sectionFields.map((field, index) => (
- {/* Text (UZ) */} + {/* Text UZ */} - {/* Text (RU) */} + {/* Text RU */} - append({ image: undefined as any, text: "", text_ru: "" }) + appendSection({ image: undefined as any, text: "", text_ru: "" }) } className="bg-gray-700 hover:bg-gray-600" > diff --git a/src/shared/config/i18n/locales/ru/translation.json b/src/shared/config/i18n/locales/ru/translation.json index cb620e5..a3550e2 100644 --- a/src/shared/config/i18n/locales/ru/translation.json +++ b/src/shared/config/i18n/locales/ru/translation.json @@ -530,5 +530,8 @@ "Yuborish": "Отправить", "Pulni o'tkazish": "Перевод средств", "To‘lov muvaffaqiyatli amalga oshirildi!": "Оплата успешно выполнена!", - "Sizga tizimga kirishga ruxsat berilmagan": "Вам не разрешен доступ к системе." + "Sizga tizimga kirishga ruxsat berilmagan": "Вам не разрешен доступ к системе.", + "Оmmaviy": "Публичный", + "Shaxsiy": "Личный", + "Status o'zgartirildi": "Статус изменён" } diff --git a/src/shared/config/i18n/locales/uz/translation.json b/src/shared/config/i18n/locales/uz/translation.json index 211a81e..b380321 100644 --- a/src/shared/config/i18n/locales/uz/translation.json +++ b/src/shared/config/i18n/locales/uz/translation.json @@ -531,5 +531,8 @@ "Yuborish": "Yuborish", "Pulni o'tkazish": "Pulni o'tkazish", "To‘lov muvaffaqiyatli amalga oshirildi!": "To‘lov muvaffaqiyatli amalga oshirildi!", - "Sizga tizimga kirishga ruxsat berilmagan": "Sizga tizimga kirishga ruxsat berilmagan" + "Sizga tizimga kirishga ruxsat berilmagan": "Sizga tizimga kirishga ruxsat berilmagan", + "Оmmaviy": "Ommaviy", + "Shaxsiy": "Shaxsiy", + "Status o'zgartirildi": "Status o'zgartirildi" }