api ulandi

This commit is contained in:
Samandar Turgunboyev
2025-10-29 18:41:59 +05:00
parent a9e99f9755
commit 2d0285dafc
64 changed files with 6319 additions and 2352 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import { addNews } from "@/pages/news/lib/api";
import { addNews, updateNews } from "@/pages/news/lib/api";
import { useNewsStore } from "@/pages/news/lib/data";
import { newsPostForm, type NewsPostFormType } from "@/pages/news/lib/form";
import { Button } from "@/shared/ui/button";
@@ -17,15 +17,57 @@ import { Textarea } from "@/shared/ui/textarea";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { ImagePlus, PlusCircle, Trash2 } from "lucide-react";
import { useEffect, useRef } from "react";
import { useFieldArray, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { toast } from "sonner";
const StepTwo = () => {
interface Data {
id: number;
title: string;
title_ru: string;
title_uz: string;
image: string;
text: string;
text_ru: string;
text_uz: string;
is_public: boolean;
category: {
name: string;
name_ru: string;
name_uz: string;
};
tag: [
{
id: number;
name: string;
name_ru: string;
name_uz: string;
},
];
post_images: [
{
image: string;
text: string;
text_ru: string;
text_uz: string;
},
];
}
const StepTwo = ({
data: detail,
id,
}: {
isEditMode: boolean;
id: string;
data: Data;
}) => {
const { t } = useTranslation();
const hasReset = useRef(false);
const navigate = useNavigate();
const { stepOneData } = useNewsStore();
const { stepOneData, resetStepOneData } = useNewsStore();
const queryClient = useQueryClient();
const form = useForm<NewsPostFormType>({
@@ -39,6 +81,33 @@ const StepTwo = () => {
},
});
useEffect(() => {
if (detail && !hasReset.current) {
// 🧠 xavfsiz map qilish
const mappedSections =
detail.post_images?.map((img) => ({
image: img.image,
text: img.text_uz,
text_ru: img.text_ru,
})) ?? [];
const mappedTags = detail.tag?.map((t) => t.name_uz) ?? [];
form.reset({
desc: detail.text_uz || "",
desc_ru: detail.text_ru || "",
is_public: detail.is_public ? "yes" : "no",
post_tags: mappedTags.length > 0 ? mappedTags : [""],
sections:
mappedSections.length > 0
? mappedSections
: [{ image: "", text: "", text_ru: "" }],
});
hasReset.current = true;
}
}, [detail, form]);
const { fields, append, remove } = useFieldArray({
control: form.control,
name: "sections",
@@ -56,7 +125,26 @@ const StepTwo = () => {
mutationFn: (body: FormData) => addNews(body),
onSuccess: () => {
queryClient.refetchQueries({ queryKey: ["all_news"] });
queryClient.refetchQueries({ queryKey: ["news_detail"] });
navigate("/news");
resetStepOneData();
},
onError: () => {
toast.error(t("Xatolik yuz berdi"), {
richColors: true,
position: "top-center",
});
},
});
const { mutate: update } = useMutation({
mutationFn: ({ body, id }: { id: number; body: FormData }) =>
updateNews({ id: id, body }),
onSuccess: () => {
queryClient.refetchQueries({ queryKey: ["news_detail"] });
queryClient.refetchQueries({ queryKey: ["all_news"] });
navigate("/news");
resetStepOneData();
},
onError: () => {
toast.error(t("Xatolik yuz berdi"), {
@@ -79,14 +167,20 @@ const StepTwo = () => {
formData.append("title", stepOneData.title);
formData.append("title_ru", stepOneData.title_ru);
formData.append("image", stepOneData.banner ?? "");
formData.append("text", stepOneData.desc);
formData.append("text_ru", stepOneData.desc_ru);
formData.append("is_public", values.is_public === "no" ? "false" : "true");
formData.append("category", stepOneData.category);
if (stepOneData.banner instanceof File) {
formData.append("image", stepOneData.banner);
}
// 🔥 sections
values.sections.forEach((section, i) => {
formData.append(`post_images[${i}]`, section.image);
if (section.image instanceof File) {
formData.append(`post_images[${i}]`, section.image);
}
formData.append(`post_text[${i}]`, section.text);
formData.append(`post_text_ru[${i}]`, section.text_ru);
});
@@ -94,8 +188,14 @@ const StepTwo = () => {
values.post_tags.forEach((tag, i) => {
formData.append(`post_tags[${i}]`, tag);
});
added(formData);
if (id) {
update({
body: formData,
id: Number(id),
});
} else {
added(formData);
}
};
return (
@@ -201,9 +301,13 @@ const StepTwo = () => {
{form.watch(`sections.${index}.image`) ? (
<div className="relative mt-2 w-48">
<img
src={URL.createObjectURL(
form.watch(`sections.${index}.image`),
)}
src={
form.watch(`sections.${index}.image`) instanceof File
? URL.createObjectURL(
form.watch(`sections.${index}.image`) as File,
)
: String(form.watch(`sections.${index}.image`) || "")
}
alt="preview"
className="rounded-lg border border-gray-700 object-cover h-40 w-full"
/>