Hamdast1/src/app/components/submit-forms/ImageForm.tsx
reza7321 213c0a70f0 امروز ۳۱ اردیبهشت
چت بات عمومی خرابه
2026-05-21 14:50:03 +03:30

217 lines
7.7 KiB
TypeScript

import { useState } from "react";
import { motion } from "motion/react";
import { SubmitFormProps, getTopicConfig } from "../../../config/topicConfig";
import { MediaUploadBox } from "./shared/MediaUploadBox";
import { TeammatesSection, Teammate } from "./shared/TeammatesSection";
import { FormInput } from "./shared/FormInput";
import { uploadImage, submitMission } from "../../../services/feedService";
import { useProfile } from "../../context/ProfileContext";
// Helper function to generate unique IDs
const generateId = () => `teammate-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
export function ImageForm({ topicId, topicTitle, onSubmit }: SubmitFormProps) {
const topicConfig = getTopicConfig(topicId);
const { refreshProfile } = useProfile();
// ===== Form Fields State =====
const [title, setTitle] = useState("");
const [learnings, setLearnings] = useState("");
// ===== Teammates State (with unique IDs and verification) =====
const [teammates, setTeammates] = useState<Teammate[]>([{ id: generateId(), phone: "" }]);
// ===== Media State =====
const [uploadedImage, setUploadedImage] = useState<string | null>(null);
const [uploadedImageFile, setUploadedImageFile] = useState<File | null>(null);
// ===== Loading State =====
const [isSubmitting, setIsSubmitting] = useState(false);
const [uploadProgress, setUploadProgress] = useState<string>("");
// ===== Media Handler =====
const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
setUploadedImageFile(file);
const reader = new FileReader();
reader.onloadend = () => setUploadedImage(reader.result as string);
reader.readAsDataURL(file);
}
};
// ===== Teammates Handlers =====
const handleAddTeammate = () => {
setTeammates([...teammates, { id: generateId(), phone: "" }]);
};
const handleRemoveTeammate = (id: string) => {
const filtered = teammates.filter((t) => t.id !== id);
setTeammates(filtered.length > 0 ? filtered : [{ id: generateId(), phone: "" }]);
};
const handleTeammateChange = (id: string, value: string) => {
setTeammates(teammates.map((t) => (t.id === id ? { ...t, phone: value, fullName: undefined, userId: undefined, error: undefined } : t)));
};
const handleTeammateVerify = (id: string, fullName: string, userId: string, error?: string) => {
setTeammates(teammates.map((t) => (t.id === id ? { ...t, fullName, userId, error } : t)));
};
const handleSubmit = async () => {
if (isSubmitting) return;
setIsSubmitting(true);
try {
// آپلود تصویر اگر وجود دارد
let imageFilename = "";
if (uploadedImageFile) {
setUploadProgress("در حال آپلود تصویر...");
const filename = await uploadImage(uploadedImageFile);
if (filename) {
imageFilename = filename;
} else {
alert("خطا در آپلود تصویر");
setIsSubmitting(false);
setUploadProgress("");
return;
}
}
// Get verified user IDs and join with comma
const verifiedUserIds = teammates
.filter((t) => t.userId)
.map((t) => t.userId)
.join(",");
// Get workflow_ID from localStorage
const workflowID = localStorage.getItem("current_workflow_ID") || "";
// ثبت نهایی ماموریت
setUploadProgress("در حال ثبت ماموریت...");
const result = await submitMission({
title: title || "",
mission_type: topicTitle,
mission_done_workflowID: workflowID,
description: learnings || "",
film: "",
image: imageFilename,
audio: "",
team_member: verifiedUserIds,
});
if (result.success) {
// بروزرسانی پروفایل (برای سکه‌های جدید)
await refreshProfile();
// فراخوانی onSubmit برای نمایش modal و هدایت به feed
onSubmit({
topicId,
title,
learnings,
teammates: verifiedUserIds ? [verifiedUserIds] : [],
mediaType: "image",
uploadedImage,
});
} else {
alert(result.message || "خطا در ثبت ماموریت");
}
} catch (error) {
console.error("Error submitting:", error);
alert("خطا در ثبت ماموریت");
} finally {
setIsSubmitting(false);
setUploadProgress("");
}
};
return (
<div className="space-y-6" dir="rtl">
{/* Image Upload */}
<MediaUploadBox
type="image"
uploadedFile={uploadedImage}
onUpload={handleImageUpload}
onRemove={() => setUploadedImage(null)}
label="تصویر چالش"
/>
{/* Teammates - Only show if config requires it */}
{topicConfig.requiresTeammates && (
<TeammatesSection
teammates={teammates}
onAdd={handleAddTeammate}
onRemove={handleRemoveTeammate}
onChange={handleTeammateChange}
onVerify={handleTeammateVerify}
/>
)}
{/* Title */}
<FormInput
label="عنوان چالش"
value={title}
onChange={setTitle}
placeholder="عنوان چالش خود را وارد کنید..."
/>
{/* Learnings */}
<FormInput
label="از این چالش چه چیزی یاد گرفتیم"
value={learnings}
onChange={setLearnings}
placeholder="توضیحات خود را وارد کنید..."
multiline
rows={6}
/>
{/* Submit Button */}
<motion.button
whileTap={{ scale: 0.95 }}
onClick={handleSubmit}
disabled={isSubmitting}
className="w-full py-4 rounded-full text-white text-base font-bold mb-6"
style={{
backgroundImage: isSubmitting
? "linear-gradient(145deg, rgba(72, 58, 105, 0.72) 0%, rgba(42, 35, 77, 0.76) 100%)"
: "linear-gradient(90deg, rgba(255,139,91,1) 0%, rgba(238,91,166,1) 45%, rgba(147,78,255,1) 100%), linear-gradient(120deg, #7c3aed 0%, #f97316 58%, #facc15 100%)",
backgroundOrigin: "border-box",
backgroundClip: "padding-box, border-box",
boxShadow: isSubmitting
? "inset 0 1px 0 rgba(255,255,255,0.12)"
: "0 10px 26px rgba(196, 87, 255, 0.35), inset 0 1px 0 rgba(255,255,255,0.35)",
border: "1px solid transparent",
opacity: isSubmitting ? 0.7 : 1,
cursor: isSubmitting ? "not-allowed" : "pointer",
}}
>
{isSubmitting ? "در حال ثبت..." : "ثبت نهایی چالش"}
</motion.button>
{/* Upload Progress Message */}
{uploadProgress && (
<motion.div
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
className="text-center mb-4 p-4 rounded-2xl"
style={{
backgroundImage: "linear-gradient(180deg, rgba(46, 27, 61, 0.88) 0%, rgba(35, 24, 62, 0.92) 100%), linear-gradient(120deg, #7c3aed 0%, #f97316 58%, #facc15 100%)",
backgroundOrigin: "border-box",
backgroundClip: "padding-box, border-box",
border: "0.5px solid transparent",
}}
>
<div className="flex items-center justify-center gap-3">
<motion.div
animate={{ rotate: 360 }}
transition={{ duration: 1, repeat: Infinity, ease: "linear" }}
className="w-5 h-5 border-2 border-[#D8B4FE] border-t-transparent rounded-full"
/>
<span className="text-[#FBE7F5] font-bold text-sm">{uploadProgress}</span>
</div>
</motion.div>
)}
</div>
);
}