62aaf2bcba
- Updated MentorProjectCard to provide more detailed success/error messages upon archiving and completing projects. - Adjusted layout for certificate generation to improve visual alignment. - Introduced resolveErrorMessage utility to standardize error message handling across the application. - Enhanced customToast functionality to handle hook failures more gracefully. - Refactored useCertificates hook to return structured responses for certificate claims and generation. - Updated useMentors hook to improve error handling and response structure for mentor operations. - Improved useNotification hook to return structured responses for marking notifications as read. - Refactored useProjects hook to provide structured responses for project creation, updates, and member assignments. - Enhanced useTasks hook to return structured responses for task creation, updates, and deletions. - Updated services to return structured responses with messages for various API calls related to certificates, mentors, notifications, projects, tasks, and user management. - Moved mentor-related types to a dedicated user.types file for better organization.
120 lines
4.2 KiB
TypeScript
120 lines
4.2 KiB
TypeScript
import { useState } from "react";
|
|
import { Link } from "lucide-react";
|
|
import { LuSendHorizontal } from "react-icons/lu";
|
|
import SubmitStatusTable from "./SubmissionStatusTable";
|
|
import { useSubmission } from "../../../../hooks/useTasks";
|
|
import type { TaskSubmissionData } from "../../../../types/task.types";
|
|
import { customToast } from "../../../utils/showToast";
|
|
|
|
interface TaskFormLinkProps {
|
|
taskId: string;
|
|
projectId?: string;
|
|
deadline?: Date;
|
|
initialSubmission?: TaskSubmissionData | null;
|
|
isProjectActive?: boolean;
|
|
}
|
|
|
|
export default function TaskFormLink({
|
|
taskId,
|
|
projectId,
|
|
deadline,
|
|
initialSubmission,
|
|
isProjectActive = true,
|
|
}: TaskFormLinkProps) {
|
|
const { submission, loading, submitLink, updateLink, remove } = useSubmission(taskId, initialSubmission, projectId);
|
|
const [inputLink, setInputLink] = useState(initialSubmission?.url_link ?? "");
|
|
const [isEditing, setIsEditing] = useState(false);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
try {
|
|
await customToast.promise(
|
|
isEditing ? updateLink(submission!.id, inputLink) : submitLink(inputLink),
|
|
{
|
|
loading: isEditing ? "Memperbarui Link..." : "Mengirim Link...",
|
|
success: (res) => ({
|
|
title: isEditing ? "Link diperbaharui" : "Link berhasil dikirim",
|
|
description:
|
|
res?.message ??
|
|
(isEditing
|
|
? "Perubahan submission Anda telah disimpan."
|
|
: "Link berhasil dikirim."),
|
|
}),
|
|
error: (err) => ({
|
|
title: isEditing ? "Gagal memperbarui link!" : "Gagal mengirim link!",
|
|
description:
|
|
err?.response?.data?.message ||
|
|
err?.message ||
|
|
"Link yang anda submit gagal dikirim",
|
|
}),
|
|
}
|
|
);
|
|
setIsEditing(false);
|
|
} catch { }
|
|
};
|
|
|
|
const handleDelete = async () => {
|
|
try {
|
|
const ok = await remove(submission!.id);
|
|
if (ok) {
|
|
setInputLink("");
|
|
setIsEditing(false);
|
|
customToast.success(
|
|
"Submission berhasil dihapus!",
|
|
ok.message
|
|
);
|
|
}
|
|
} catch (err: any) {
|
|
customToast.error(
|
|
"Gagal menghapus submission!",
|
|
err?.response?.data?.message || "Terjadi kesalahan saat menghapus submission."
|
|
);
|
|
}
|
|
};
|
|
|
|
if (submission && !isEditing) {
|
|
return (
|
|
<SubmitStatusTable
|
|
type="link"
|
|
link={submission.url_link ?? ""}
|
|
submittedAt={new Date(submission.submitted_at)}
|
|
deadline={deadline}
|
|
onEdit={() => setIsEditing(true)}
|
|
onDelete={handleDelete}
|
|
disabled={!isProjectActive}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit} className="space-y-5">
|
|
<div className="space-y-1.5">
|
|
<label className="text-[15px] font-bold text-font-shade tracking-wide block">
|
|
{isEditing ? "Update Submission Link" : "Submission Link"}
|
|
</label>
|
|
<div className="relative flex items-center">
|
|
<span className="absolute left-3.5 text-font/70">
|
|
<Link className="w-4 h-4 stroke-[2]" />
|
|
</span>
|
|
<input
|
|
type="url" required
|
|
placeholder="https://example.com/"
|
|
value={inputLink}
|
|
onChange={(e) => setInputLink(e.target.value)}
|
|
className="w-full pl-10 pr-4 py-2.5 bg-box-primary/50 border border-box-border rounded-lg text-sm placeholder-font text-font focus:outline-none focus:bg-white focus:border-red-600 focus:ring-1 focus:ring-red-600 font-medium"
|
|
/>
|
|
</div>
|
|
<p className="text-[13px] text-font font-medium pt-0.5">
|
|
Pastikan link yang disubmit bisa diakses oleh publik.
|
|
</p>
|
|
</div>
|
|
<button
|
|
type="submit" disabled={loading || !isProjectActive}
|
|
className="w-full bg-[#B30000] hover:bg-[#990000] disabled:opacity-60 text-white font-bold py-3 rounded-xl transition-colors shadow-md flex items-center justify-center gap-2 tracking-wide cursor-pointer disabled:cursor-not-allowed disabled:hover:bg-[#990000]"
|
|
>
|
|
{loading ? "Mengirim..." : isEditing ? "Update Submission" : "Submit Task"}
|
|
<LuSendHorizontal className="w-4 h-4 stroke-[2.5]" />
|
|
</button>
|
|
</form>
|
|
);
|
|
} |