[QUDO-53,QUDO-54] feat:update form create penugasan Ta, update sidebar SPV,update table hasil upload media Ta
This commit is contained in:
parent
1cd3019c6b
commit
bd527e102c
|
|
@ -32,6 +32,7 @@ import {
|
||||||
saveUserRolePlacements,
|
saveUserRolePlacements,
|
||||||
} from "@/service/management-user/management-user";
|
} from "@/service/management-user/management-user";
|
||||||
import { loading } from "@/config/swal";
|
import { loading } from "@/config/swal";
|
||||||
|
import { Eye, EyeOff } from "lucide-react";
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
name: z.string({
|
name: z.string({
|
||||||
|
|
@ -79,6 +80,14 @@ export default function AddExpertForm() {
|
||||||
const [userCompetencies, setUserCompetencies] = useState<any>();
|
const [userCompetencies, setUserCompetencies] = useState<any>();
|
||||||
const [userExperiences, setUserExperiences] = useState<any>();
|
const [userExperiences, setUserExperiences] = useState<any>();
|
||||||
const [userLevels, setUserLevels] = useState<any>();
|
const [userLevels, setUserLevels] = useState<any>();
|
||||||
|
const [passwordType, setPasswordType] = useState("password");
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
|
const togglePasswordType = () => {
|
||||||
|
setPasswordType((prevType) =>
|
||||||
|
prevType === "password" ? "text" : "password"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const roleSelection = [
|
const roleSelection = [
|
||||||
{
|
{
|
||||||
|
|
@ -115,7 +124,7 @@ export default function AddExpertForm() {
|
||||||
username: data.username,
|
username: data.username,
|
||||||
email: data.email,
|
email: data.email,
|
||||||
password: data.password,
|
password: data.password,
|
||||||
adress: "",
|
address: "",
|
||||||
roleId: "EXP-ID",
|
roleId: "EXP-ID",
|
||||||
phoneNumber: data.phoneNumber,
|
phoneNumber: data.phoneNumber,
|
||||||
userCompetencyId: data.skills,
|
userCompetencyId: data.skills,
|
||||||
|
|
@ -308,12 +317,22 @@ export default function AddExpertForm() {
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Password</FormLabel>
|
<FormLabel>Password</FormLabel>
|
||||||
<Input
|
<div className="relative">
|
||||||
type="password"
|
<Input
|
||||||
value={field.value}
|
value={field.value}
|
||||||
placeholder="Masukkan Password"
|
type={showPassword ? "text" : "password"}
|
||||||
onChange={field.onChange}
|
placeholder="Masukkan Password"
|
||||||
/>
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowPassword(!showPassword)}
|
||||||
|
className="absolute right-3 top-1/2 -translate-y-1/2 text-default-500 hover:text-default-700"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
|
{showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import { Link } from "@/components/navigation";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
import { deleteCategory } from "@/service/settings/settings";
|
import { deleteCategory } from "@/service/settings/settings";
|
||||||
import { deleteTask } from "@/service/task";
|
import { deleteTaskTa } from "@/service/task";
|
||||||
import { error, loading } from "@/lib/swal";
|
import { error, loading } from "@/lib/swal";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
|
|
@ -109,7 +109,7 @@ const useTableColumns = () => {
|
||||||
|
|
||||||
async function deleteProcess(id: any) {
|
async function deleteProcess(id: any) {
|
||||||
loading();
|
loading();
|
||||||
const resDelete = await deleteTask(id);
|
const resDelete = await deleteTaskTa(id);
|
||||||
|
|
||||||
if (resDelete?.error) {
|
if (resDelete?.error) {
|
||||||
error(resDelete.message);
|
error(resDelete.message);
|
||||||
|
|
@ -185,13 +185,15 @@ const useTableColumns = () => {
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
<DropdownMenuItem
|
{roleId == 11 && (
|
||||||
onClick={() => TaskDelete(row.original.id)}
|
<DropdownMenuItem
|
||||||
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
onClick={() => TaskDelete(row.original.id)}
|
||||||
>
|
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
||||||
<Trash2 className="w-4 h-4 me-1.5" />
|
>
|
||||||
Delete
|
<Trash2 className="w-4 h-4 me-1.5" />
|
||||||
</DropdownMenuItem>
|
Delete
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import {
|
||||||
getAcceptanceAssignmentStatus,
|
getAcceptanceAssignmentStatus,
|
||||||
getAssignmentResponseList,
|
getAssignmentResponseList,
|
||||||
getMediaUpload,
|
getMediaUpload,
|
||||||
|
getMediaUploadTa,
|
||||||
getTask,
|
getTask,
|
||||||
getTaskTa,
|
getTaskTa,
|
||||||
getUserLevelForAssignments,
|
getUserLevelForAssignments,
|
||||||
|
|
@ -407,7 +408,7 @@ export default function FormTaskTaDetail() {
|
||||||
|
|
||||||
const fetchAllData = async () => {
|
const fetchAllData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await getMediaUpload(id, userLevelId);
|
const response = await getMediaUploadTa(id, userLevelId);
|
||||||
setUploadResults(response?.data?.data || []);
|
setUploadResults(response?.data?.data || []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching all data:", error);
|
console.error("Error fetching all data:", error);
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import {
|
||||||
createTaskTa,
|
createTaskTa,
|
||||||
getTask,
|
getTask,
|
||||||
getUserLevelForAssignments,
|
getUserLevelForAssignments,
|
||||||
|
getUserLevelForExpert,
|
||||||
} from "@/service/task";
|
} from "@/service/task";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
|
|
@ -54,6 +55,11 @@ import { DateRange } from "react-day-picker";
|
||||||
import TimePicker from "react-time-picker";
|
import TimePicker from "react-time-picker";
|
||||||
import "react-time-picker/dist/TimePicker.css";
|
import "react-time-picker/dist/TimePicker.css";
|
||||||
import "react-clock/dist/Clock.css";
|
import "react-clock/dist/Clock.css";
|
||||||
|
import {
|
||||||
|
AdministrationLevelList,
|
||||||
|
getListCompetencies,
|
||||||
|
getListExperiences,
|
||||||
|
} from "@/service/management-user/management-user";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -129,7 +135,14 @@ export default function FormTaskTa() {
|
||||||
const [detail, setDetail] = useState<taskDetail>();
|
const [detail, setDetail] = useState<taskDetail>();
|
||||||
const [refresh] = useState(false);
|
const [refresh] = useState(false);
|
||||||
const [listDest, setListDest] = useState([]);
|
const [listDest, setListDest] = useState([]);
|
||||||
const [checkedLevels, setCheckedLevels] = useState(new Set());
|
const [userExperiences, setUserExperiences] = useState<any>();
|
||||||
|
const [userLevels, setUserLevels] = useState<any>();
|
||||||
|
const [userCompetencies, setUserCompetencies] = useState<any[]>([]);
|
||||||
|
const [selectedCompetencies, setSelectedCompetencies] = useState<Set<number>>(
|
||||||
|
new Set()
|
||||||
|
);
|
||||||
|
const [listExpert, setListExpert] = useState<any[]>([]);
|
||||||
|
const [checkedLevels, setCheckedLevels] = useState<Set<number>>(new Set());
|
||||||
const [expandedPolda, setExpandedPolda] = useState([{}]);
|
const [expandedPolda, setExpandedPolda] = useState([{}]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [audioFile, setAudioFile] = useState<File | null>(null);
|
const [audioFile, setAudioFile] = useState<File | null>(null);
|
||||||
|
|
@ -171,37 +184,57 @@ export default function FormTaskTa() {
|
||||||
mode: "all",
|
mode: "all",
|
||||||
});
|
});
|
||||||
|
|
||||||
// const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
useEffect(() => {
|
||||||
// const selectedValue = Number(event.target.value);
|
getDataAdditional();
|
||||||
// setMainType(selectedValue);
|
}, []);
|
||||||
|
|
||||||
// setPlatformTypeVisible(selectedValue === 2);
|
async function getDataAdditional() {
|
||||||
|
const resCompetencies = await getListCompetencies();
|
||||||
|
console.log("competency", resCompetencies);
|
||||||
|
setUserCompetencies(resCompetencies?.data?.data);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchPoldaPolres() {
|
async function fetchListExpert() {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await getUserLevelForAssignments();
|
const response = await getUserLevelForExpert(id);
|
||||||
setListDest(response?.data?.data.list);
|
setListExpert(response?.data?.data);
|
||||||
console.log("polda", response?.data?.data?.list);
|
console.log("tenaga ahli", response?.data?.data);
|
||||||
const initialExpandedState = response?.data?.data.list.reduce(
|
|
||||||
(acc: any, polda: any) => {
|
|
||||||
acc[polda.id] = false;
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
setExpandedPolda(initialExpandedState);
|
|
||||||
console.log("polres", initialExpandedState);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching Polda/Polres data:", error);
|
console.error("Error fetching Polda/Polres data:", error);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fetchPoldaPolres();
|
fetchListExpert();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchExpertsForCompetencies = async () => {
|
||||||
|
const allExperts: any[] = [];
|
||||||
|
|
||||||
|
for (const compId of Array.from(selectedCompetencies)) {
|
||||||
|
const response = await getUserLevelForExpert(compId);
|
||||||
|
const experts = response?.data?.data || [];
|
||||||
|
allExperts.push(...experts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hapus duplikat expert berdasarkan ID
|
||||||
|
const uniqueExperts = Array.from(
|
||||||
|
new Map(allExperts.map((e) => [e.id, e])).values()
|
||||||
|
);
|
||||||
|
|
||||||
|
setListExpert(uniqueExperts);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (selectedCompetencies.size > 0) {
|
||||||
|
fetchExpertsForCompetencies();
|
||||||
|
} else {
|
||||||
|
setListExpert([]);
|
||||||
|
}
|
||||||
|
}, [selectedCompetencies]);
|
||||||
|
|
||||||
// };
|
// };
|
||||||
const handleCheckboxChange = (levelId: number) => {
|
const handleCheckboxChange = (levelId: number) => {
|
||||||
setCheckedLevels((prev) => {
|
setCheckedLevels((prev) => {
|
||||||
|
|
@ -215,10 +248,22 @@ export default function FormTaskTa() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePoldaPolresChange = () => {
|
const handleExpertChange = () => {
|
||||||
return Array.from(checkedLevels).join(","); // Mengonversi Set ke string
|
return Array.from(checkedLevels).join(","); // Mengonversi Set ke string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCompetencyChange = async (competencyId: number) => {
|
||||||
|
setSelectedCompetencies((prev) => {
|
||||||
|
const updated = new Set(prev);
|
||||||
|
if (updated.has(competencyId)) {
|
||||||
|
updated.delete(competencyId);
|
||||||
|
} else {
|
||||||
|
updated.add(competencyId);
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleUnitChange = (
|
const handleUnitChange = (
|
||||||
key: keyof typeof unitSelection,
|
key: keyof typeof unitSelection,
|
||||||
value: boolean
|
value: boolean
|
||||||
|
|
@ -305,61 +350,22 @@ export default function FormTaskTa() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const save = async (data: TaskSchema) => {
|
const save = async (data: TaskSchema) => {
|
||||||
const fileTypeMapping = {
|
|
||||||
all: "1",
|
|
||||||
video: "2",
|
|
||||||
audio: "4",
|
|
||||||
image: "3",
|
|
||||||
text: "5",
|
|
||||||
};
|
|
||||||
|
|
||||||
const unitMapping = {
|
|
||||||
allUnit: "0",
|
|
||||||
mabes: "1",
|
|
||||||
polda: "2",
|
|
||||||
polres: "3",
|
|
||||||
satker: "4",
|
|
||||||
};
|
|
||||||
const assignmentPurposeString = Object.keys(unitSelection)
|
|
||||||
.filter((key) => unitSelection[key as keyof typeof unitSelection])
|
|
||||||
.map((key) => unitMapping[key as keyof typeof unitMapping])
|
|
||||||
.join(",");
|
|
||||||
|
|
||||||
const selectedOutputs = Object.keys(expertise)
|
|
||||||
.filter((key) => expertise[key as keyof typeof expertise])
|
|
||||||
.map((key) => fileTypeMapping[key as keyof typeof fileTypeMapping])
|
|
||||||
.join(",");
|
|
||||||
|
|
||||||
const requestData: {
|
const requestData: {
|
||||||
id?: number;
|
id?: number;
|
||||||
title: string;
|
title: string;
|
||||||
assignedToLevel: any;
|
|
||||||
assignedToUsers: any;
|
assignedToUsers: any;
|
||||||
assignmentTypeId: string;
|
assignmentTypeId: string;
|
||||||
fileTypeOutput: string;
|
|
||||||
narration: string;
|
narration: string;
|
||||||
platformType: string | null;
|
|
||||||
assignmentMainTypeId: any;
|
|
||||||
assignmentType: string;
|
assignmentType: string;
|
||||||
assignedToRole: string;
|
|
||||||
broadcastType: string;
|
|
||||||
expertCompetencies: string;
|
expertCompetencies: string;
|
||||||
attachmentUrl: string[];
|
attachmentUrl: string[];
|
||||||
} = {
|
} = {
|
||||||
...data,
|
...data,
|
||||||
// assignmentType,
|
assignedToUsers: handleExpertChange(),
|
||||||
// assignmentCategory,
|
|
||||||
assignedToLevel: handlePoldaPolresChange(),
|
|
||||||
assignedToUsers: assignmentPurposeString,
|
|
||||||
assignedToRole: selectedTarget,
|
|
||||||
assignmentType: taskType,
|
assignmentType: taskType,
|
||||||
broadcastType: broadcastType,
|
|
||||||
assignmentMainTypeId: mainType,
|
|
||||||
assignmentTypeId: type,
|
assignmentTypeId: type,
|
||||||
fileTypeOutput: selectedOutputs,
|
|
||||||
narration: data.naration,
|
narration: data.naration,
|
||||||
platformType: "",
|
expertCompetencies: Array.from(selectedCompetencies).join(","),
|
||||||
expertCompetencies: "1,2,3",
|
|
||||||
title: data.title,
|
title: data.title,
|
||||||
attachmentUrl: links,
|
attachmentUrl: links,
|
||||||
};
|
};
|
||||||
|
|
@ -622,121 +628,7 @@ export default function FormTaskTa() {
|
||||||
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col sm:flex-row lg:flex-row sm:items-center lg:items-center">
|
|
||||||
<div className="mt-5 space-y-2">
|
|
||||||
<Label>{t("assignment-selection")}</Label>
|
|
||||||
<Select onValueChange={setSelectedTarget}>
|
|
||||||
<SelectTrigger size="md">
|
|
||||||
<SelectValue placeholder="Choose" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="3,4">Semua Pengguna</SelectItem>
|
|
||||||
<SelectItem value="4">Kontributor</SelectItem>
|
|
||||||
<SelectItem value="3">Approver</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-wrap gap-3 mt-5 lg:pt-7 lg:ml-3 ">
|
|
||||||
{Object.keys(unitSelection).map((key) => (
|
|
||||||
<div className="flex items-center gap-2" key={key}>
|
|
||||||
<Checkbox
|
|
||||||
id={key}
|
|
||||||
checked={unitSelection[key as keyof typeof unitSelection]}
|
|
||||||
onCheckedChange={(value) =>
|
|
||||||
handleUnitChange(
|
|
||||||
key as keyof typeof unitSelection,
|
|
||||||
value as boolean
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Label htmlFor={key}>
|
|
||||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
|
||||||
</Label>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="mt-6 lg:pt-6 lg:pl-3">
|
|
||||||
<Dialog>
|
|
||||||
<DialogTrigger asChild>
|
|
||||||
<Button variant="soft" size="sm" color="primary">
|
|
||||||
[{t("custom")}]
|
|
||||||
</Button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Daftar Wilayah Polda dan Polres</DialogTitle>
|
|
||||||
</DialogHeader>
|
|
||||||
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
|
|
||||||
{listDest.map((polda: any) => (
|
|
||||||
<div key={polda.id} className="border p-2">
|
|
||||||
<Label className="flex items-center">
|
|
||||||
<Checkbox
|
|
||||||
checked={checkedLevels.has(polda.id)}
|
|
||||||
onCheckedChange={() =>
|
|
||||||
handleCheckboxChange(polda.id)
|
|
||||||
}
|
|
||||||
className="mr-3"
|
|
||||||
/>
|
|
||||||
{polda.name}
|
|
||||||
<button
|
|
||||||
onClick={() => toggleExpand(polda.id)}
|
|
||||||
className="ml-2 focus:outline-none"
|
|
||||||
>
|
|
||||||
{expandedPolda[polda.id] ? (
|
|
||||||
<ChevronUp size={16} />
|
|
||||||
) : (
|
|
||||||
<ChevronDown size={16} />
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</Label>
|
|
||||||
{expandedPolda[polda.id] && (
|
|
||||||
<div className="ml-6 mt-2">
|
|
||||||
<Label className="block">
|
|
||||||
<Checkbox
|
|
||||||
checked={polda?.subDestination?.every(
|
|
||||||
(polres: any) =>
|
|
||||||
checkedLevels.has(polres.id)
|
|
||||||
)}
|
|
||||||
onCheckedChange={(isChecked) => {
|
|
||||||
const updatedLevels = new Set(
|
|
||||||
checkedLevels
|
|
||||||
);
|
|
||||||
polda?.subDestination?.forEach(
|
|
||||||
(polres: any) => {
|
|
||||||
if (isChecked) {
|
|
||||||
updatedLevels.add(polres.id);
|
|
||||||
} else {
|
|
||||||
updatedLevels.delete(polres.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
setCheckedLevels(updatedLevels);
|
|
||||||
}}
|
|
||||||
className="mr-2"
|
|
||||||
/>
|
|
||||||
Pilih Semua Polres
|
|
||||||
</Label>
|
|
||||||
{polda?.subDestination?.map((polres: any) => (
|
|
||||||
<Label key={polres.id} className="block mt-1">
|
|
||||||
<Checkbox
|
|
||||||
checked={checkedLevels.has(polres.id)}
|
|
||||||
onCheckedChange={() =>
|
|
||||||
handleCheckboxChange(polres.id)
|
|
||||||
}
|
|
||||||
className="mr-2"
|
|
||||||
/>
|
|
||||||
{polres.name}
|
|
||||||
</Label>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
<Label>{t("assigment-type")} </Label>
|
<Label>{t("assigment-type")} </Label>
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
|
|
@ -793,21 +685,14 @@ export default function FormTaskTa() {
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
<Label>{t("areas-expertise")}</Label>
|
<Label>{t("areas-expertise")}</Label>
|
||||||
<div className="flex flex-wrap gap-4">
|
<div className="flex flex-wrap gap-4">
|
||||||
{Object.keys(expertise).map((key) => (
|
{userCompetencies?.map((item: any) => (
|
||||||
<div className="flex items-center gap-2" key={key}>
|
<div className="flex items-center gap-2" key={item.id}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={key}
|
id={`comp-${item.id}`}
|
||||||
checked={expertise[key as keyof typeof expertise]}
|
checked={selectedCompetencies.has(item.id)}
|
||||||
onCheckedChange={(value) =>
|
onCheckedChange={() => handleCompetencyChange(item.id)}
|
||||||
handleExpertiseOutputChange(
|
|
||||||
key as keyof typeof expertise,
|
|
||||||
value as boolean
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Label htmlFor={key}>
|
<Label htmlFor={`comp-${item.id}`}>{item.name}</Label>
|
||||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
|
||||||
</Label>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -815,23 +700,34 @@ export default function FormTaskTa() {
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
<Label>{t("choose-expert")}</Label>
|
<Label>{t("choose-expert")}</Label>
|
||||||
<div className="flex flex-wrap gap-4">
|
<div className="flex flex-wrap gap-4">
|
||||||
{Object.keys(expert).map((key) => (
|
<Dialog>
|
||||||
<div className="flex items-center gap-2" key={key}>
|
<DialogTrigger asChild>
|
||||||
<Checkbox
|
<Button variant="soft" size="sm" color="primary">
|
||||||
id={key}
|
[{"Pilih Tenaga Ahli"}]
|
||||||
checked={expert[key as keyof typeof expert]}
|
</Button>
|
||||||
onCheckedChange={(value) =>
|
</DialogTrigger>
|
||||||
handleExpertOutputChange(
|
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
|
||||||
key as keyof typeof expert,
|
<DialogHeader>
|
||||||
value as boolean
|
<DialogTitle>Daftar Tenaga Ahli</DialogTitle>
|
||||||
)
|
</DialogHeader>
|
||||||
}
|
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
|
||||||
/>
|
{listExpert?.map((expert: any) => (
|
||||||
<Label htmlFor={key}>
|
<div key={expert.id} className="border p-2">
|
||||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
<Label className="flex items-center">
|
||||||
</Label>
|
<Checkbox
|
||||||
</div>
|
checked={checkedLevels.has(expert.id)}
|
||||||
))}
|
onCheckedChange={() =>
|
||||||
|
handleCheckboxChange(expert.id)
|
||||||
|
}
|
||||||
|
className="mr-3"
|
||||||
|
/>
|
||||||
|
{expert.fullname}
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,8 @@ const formWaveSurferOptions = (ref: any) => ({
|
||||||
barWidth: 3,
|
barWidth: 3,
|
||||||
barRadius: 3,
|
barRadius: 3,
|
||||||
responsive: true,
|
responsive: true,
|
||||||
height: 150, // If true, normalize by the maximum peak instead of 1.0.
|
height: 150,
|
||||||
normalize: true, // Use the PeakCache to improve rendering speed of large waveforms.
|
normalize: true,
|
||||||
partialRender: true,
|
partialRender: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
28
lib/menus.ts
28
lib/menus.ts
|
|
@ -2763,20 +2763,20 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
icon: "uiw:user-delete",
|
icon: "uiw:user-delete",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
href: "/supervisor/communications/ptt",
|
// href: "/supervisor/communications/ptt",
|
||||||
label: t("ptt"),
|
// label: t("ptt"),
|
||||||
active: pathname.includes("/communications/ptt"),
|
// active: pathname.includes("/communications/ptt"),
|
||||||
icon: "clarity:employee-group-line",
|
// icon: "clarity:employee-group-line",
|
||||||
children: [],
|
// children: [],
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
href: "/supervisor/communications/web-chat",
|
// href: "/supervisor/communications/web-chat",
|
||||||
label: t("web-chat"),
|
// label: t("web-chat"),
|
||||||
active: pathname.includes("/communications/web-chat"),
|
// active: pathname.includes("/communications/web-chat"),
|
||||||
icon: "clarity:employee-group-line",
|
// icon: "clarity:employee-group-line",
|
||||||
children: [],
|
// children: [],
|
||||||
},
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,11 @@ export async function getMediaUpload(id: any, userLevelId: any) {
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getMediaUploadTa(id: any, userLevelId: any) {
|
||||||
|
const url = `/assignment-expert/media-uploads?id=${id}&userLevelId=${userLevelId}`;
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function forwardTask(data: any) {
|
export async function forwardTask(data: any) {
|
||||||
const url = "assignment/forward";
|
const url = "assignment/forward";
|
||||||
return httpPostInterceptor(url, data);
|
return httpPostInterceptor(url, data);
|
||||||
|
|
@ -63,11 +68,21 @@ export async function deleteTask(id: any) {
|
||||||
return httpDeleteInterceptor(url);
|
return httpDeleteInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deleteTaskTa(id: any) {
|
||||||
|
const url = `assignment-expert?id=${id}`;
|
||||||
|
return httpDeleteInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function getUserLevelForAssignments() {
|
export async function getUserLevelForAssignments() {
|
||||||
const url = "/users/user-levels/assignment";
|
const url = "/users/user-levels/assignment";
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getUserLevelForExpert(id: any) {
|
||||||
|
const url = `/users/assignment-expert?competencyIds=${id}`;
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function getAssignmentResponseList(id: any) {
|
export async function getAssignmentResponseList(id: any) {
|
||||||
const url = `assignment/response?assignmentId=${id}`;
|
const url = `assignment/response?assignmentId=${id}`;
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue