api ulandi
This commit is contained in:
@@ -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"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user