feat : update tenaga-ahli
This commit is contained in:
parent
146bd8d782
commit
841d63b2cc
|
|
@ -23,27 +23,30 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { AdministrationLevelList, getListCompetencies, getListExperiences, saveUserInternal, saveUserRolePlacements } from "@/service/management-user/management-user";
|
||||||
|
import { loading } from "@/config/swal";
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
name: z.string({
|
name: z.string({
|
||||||
required_error: "Required",
|
required_error: "Required",
|
||||||
}),
|
}),
|
||||||
|
username: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
password: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
phoneNumber: z.string({
|
phoneNumber: z.string({
|
||||||
required_error: "Required",
|
required_error: "Required",
|
||||||
}),
|
}),
|
||||||
email: z.string({
|
email: z.string({
|
||||||
required_error: "Required",
|
required_error: "Required",
|
||||||
}),
|
}),
|
||||||
position: z.string({
|
|
||||||
required_error: "Required",
|
|
||||||
}),
|
|
||||||
region: z.string({
|
|
||||||
required_error: "Required",
|
|
||||||
}),
|
|
||||||
skills: z.string({
|
skills: z.string({
|
||||||
required_error: "Required",
|
required_error: "Required",
|
||||||
}),
|
}),
|
||||||
experience: z.string({
|
experiences: z.string({
|
||||||
required_error: "Required",
|
required_error: "Required",
|
||||||
}),
|
}),
|
||||||
company: z.string({
|
company: z.string({
|
||||||
|
|
@ -51,12 +54,34 @@ const FormSchema = z.object({
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export type Placements = {
|
||||||
|
index: number;
|
||||||
|
roleId?: string;
|
||||||
|
userLevelId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export default function AddExpertForm() {
|
export default function AddExpertForm() {
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const form = useForm<z.infer<typeof FormSchema>>({
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
resolver: zodResolver(FormSchema),
|
resolver: zodResolver(FormSchema),
|
||||||
});
|
});
|
||||||
|
const [incrementId, setIncrementId] = useState(1);
|
||||||
|
const [placementRows, setPlacementRows] = useState<Placements[]>([{ index: 0, roleId: "", userLevelId: 0 }]);
|
||||||
|
const [userCompetencies, setUserCompetencies] = useState<any>();
|
||||||
|
const [userExperiences, setUserExperiences] = useState<any>();
|
||||||
|
const [userLevels, setUserLevels] = useState<any>();
|
||||||
|
|
||||||
|
const roleSelection = [
|
||||||
|
{
|
||||||
|
id: "11",
|
||||||
|
name: "Koor Kurator",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "12",
|
||||||
|
name: "Kurator",
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
|
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
|
|
@ -77,9 +102,85 @@ export default function AddExpertForm() {
|
||||||
const save = async (data: z.infer<typeof FormSchema>) => {
|
const save = async (data: z.infer<typeof FormSchema>) => {
|
||||||
console.log("data", data);
|
console.log("data", data);
|
||||||
|
|
||||||
// successSubmit();
|
const dataReq = {
|
||||||
|
firstName: data.name,
|
||||||
|
username: data.username,
|
||||||
|
email: data.email,
|
||||||
|
password: data.password,
|
||||||
|
adress: "",
|
||||||
|
roleId: "EXP-ID",
|
||||||
|
phoneNumber: data.phoneNumber,
|
||||||
|
userCompetencyId: data.skills,
|
||||||
|
userExperienceId: data.experiences,
|
||||||
|
companyName: data.company,
|
||||||
|
}
|
||||||
|
|
||||||
|
loading();
|
||||||
|
const res = await saveUserInternal(dataReq);
|
||||||
|
const resData = res?.data?.data;
|
||||||
|
const userProfileId = resData.id;
|
||||||
|
|
||||||
|
var placementArr: any[] = [];
|
||||||
|
placementRows.forEach((row: any) => {
|
||||||
|
placementArr.push({
|
||||||
|
roleId: Number(row.roleId),
|
||||||
|
userLevelId: Number(row.userLevelId),
|
||||||
|
userProfileId: userProfileId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const dataReq2 = {
|
||||||
|
userId: userProfileId,
|
||||||
|
placements: placementArr
|
||||||
|
}
|
||||||
|
const res2 = await saveUserRolePlacements(dataReq2);
|
||||||
|
const resData2 = res2?.data?.data;
|
||||||
|
|
||||||
|
success("/admin/add-experts");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function success(redirect: string): void {
|
||||||
|
MySwal.fire({
|
||||||
|
title: '<p class="text-green-600 font-bold">Sukses</p>',
|
||||||
|
icon: "success",
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
confirmButtonText: '<span class="text-white">OK</span>',
|
||||||
|
allowOutsideClick: false,
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
router.push(redirect);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getDataAdditional();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function getDataAdditional() {
|
||||||
|
const resCompetencies = await getListCompetencies();
|
||||||
|
setUserCompetencies(resCompetencies?.data?.data);
|
||||||
|
|
||||||
|
const resExperiences = await getListExperiences();
|
||||||
|
setUserExperiences(resExperiences?.data?.data);
|
||||||
|
|
||||||
|
const resUserLevels = await AdministrationLevelList();
|
||||||
|
const data = resUserLevels?.data?.data;
|
||||||
|
var levelsArr: any[] = [];
|
||||||
|
data.forEach((levels: any) => {
|
||||||
|
levelsArr.push({
|
||||||
|
id: levels.id,
|
||||||
|
label: levels.name,
|
||||||
|
name: levels.name,
|
||||||
|
value: String(levels.id),
|
||||||
|
levelNumber: levels.levelNumber,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setUserLevels(levelsArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function successSubmit() {
|
function successSubmit() {
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
title: "Sukses",
|
title: "Sukses",
|
||||||
|
|
@ -92,6 +193,29 @@ export default function AddExpertForm() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSelectionChange = (index: number, type: "roleId" | "userLevelId", value: string) => {
|
||||||
|
setPlacementRows((prevRows) =>
|
||||||
|
prevRows.map((row) =>
|
||||||
|
row.index === index ? { ...row, [type]: value } : row
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const handleRemoveRow = (index: number) => {
|
||||||
|
console.log(index);
|
||||||
|
console.log(placementRows);
|
||||||
|
const newPlacements = placementRows.filter((row) => row.index != index);
|
||||||
|
console.log(newPlacements);
|
||||||
|
setPlacementRows(newPlacements);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddRow = () => {
|
||||||
|
setPlacementRows((prevRows: any) => [...prevRows, { index: incrementId, roleId: "", userLevelId: 0 }]);
|
||||||
|
setIncrementId((prevId) => prevId + 1);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
|
|
@ -118,6 +242,22 @@ export default function AddExpertForm() {
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="username"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Username</FormLabel>
|
||||||
|
<Input
|
||||||
|
value={field.value}
|
||||||
|
placeholder="Masukkan Username"
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="phoneNumber"
|
name="phoneNumber"
|
||||||
|
|
@ -152,45 +292,16 @@ export default function AddExpertForm() {
|
||||||
/>
|
/>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="position"
|
name="password"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Posisi</FormLabel>
|
<FormLabel>Password</FormLabel>
|
||||||
<Select onValueChange={field.onChange} value={field.value}>
|
<Input
|
||||||
<FormControl>
|
type="password"
|
||||||
<SelectTrigger>
|
value={field.value}
|
||||||
<SelectValue placeholder="Pilih Region" />
|
placeholder="Masukkan Password"
|
||||||
</SelectTrigger>
|
onChange={field.onChange}
|
||||||
</FormControl>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="koor-kurator">Koor Kurator</SelectItem>
|
|
||||||
<SelectItem value="kurator">Kurator</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="region"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>Wilayah</FormLabel>
|
|
||||||
<Select onValueChange={field.onChange} value={field.value}>
|
|
||||||
<FormControl>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue placeholder="Pilih Region" />
|
|
||||||
</SelectTrigger>
|
|
||||||
</FormControl>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="nasional">Nasional</SelectItem>
|
|
||||||
<SelectItem value="jakarta">DKI Jakarta</SelectItem>
|
|
||||||
<SelectItem value="jabar">Jawa Barat</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|
@ -208,19 +319,20 @@ export default function AddExpertForm() {
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="komunikasi">Komunikasi</SelectItem>
|
{userCompetencies?.map((item: any) => (
|
||||||
<SelectItem value="hukum">Hukum</SelectItem>
|
<SelectItem key={item.id} value={String(item.id)}>
|
||||||
<SelectItem value="bahasa">Bahasa</SelectItem>
|
{item.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="experience"
|
name="experiences"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Pengalaman</FormLabel>
|
<FormLabel>Pengalaman</FormLabel>
|
||||||
|
|
@ -231,15 +343,13 @@ export default function AddExpertForm() {
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="akademisi">Akademisi</SelectItem>
|
{userExperiences?.map((item: any) => (
|
||||||
<SelectItem value="praktisi">Praktisi</SelectItem>
|
<SelectItem key={item.id} value={String(item.id)}>
|
||||||
<SelectItem value="akademisi+praktisi">
|
{item.name}
|
||||||
Akademisi + Praktisi
|
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
@ -261,6 +371,59 @@ export default function AddExpertForm() {
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div className="mt-4">
|
||||||
|
<FormLabel>Penempatan</FormLabel>
|
||||||
|
{placementRows?.map((row: any) => (
|
||||||
|
<div key={row.index} className="flex items-center gap-2 my-2">
|
||||||
|
<Select onValueChange={(e) => handleSelectionChange(row.index, "roleId", e)} >
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Pilih Role" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{roleSelection?.map((item: any) => (
|
||||||
|
<SelectItem key={item.id} value={String(item.id)}>
|
||||||
|
{item.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<Select onValueChange={(e) => handleSelectionChange(row.index, "userLevelId", e)}>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Pilih User Level" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{userLevels?.map((item: any) => (
|
||||||
|
<SelectItem key={item.id} value={String(item.id)}>
|
||||||
|
{item.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
{placementRows.length > 1 && (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
size="md"
|
||||||
|
color="destructive"
|
||||||
|
onClick={() => handleRemoveRow(row.index)}
|
||||||
|
>
|
||||||
|
Hapus
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
size="md"
|
||||||
|
onClick={() => handleAddRow()}
|
||||||
|
>
|
||||||
|
Tambah
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-row justify-end gap-2 mt-4 pt-4">
|
<div className="flex flex-row justify-end gap-2 mt-4 pt-4">
|
||||||
<Button
|
<Button
|
||||||
size="md"
|
size="md"
|
||||||
|
|
|
||||||
|
|
@ -434,7 +434,7 @@ export default function FormContestDetail() {
|
||||||
fileTypeId: string,
|
fileTypeId: string,
|
||||||
duration: string
|
duration: string
|
||||||
) {
|
) {
|
||||||
console.log(idx, id, file, fileTypeId, duration);
|
console.log("Param Upload : ", idx, id, file, fileTypeId, duration);
|
||||||
|
|
||||||
const resCsrf = await getCsrfToken();
|
const resCsrf = await getCsrfToken();
|
||||||
const csrfToken = resCsrf?.data?.token;
|
const csrfToken = resCsrf?.data?.token;
|
||||||
|
|
@ -449,7 +449,7 @@ export default function FormContestDetail() {
|
||||||
retryDelays: [0, 3000, 6000, 12_000, 24_000],
|
retryDelays: [0, 3000, 6000, 12_000, 24_000],
|
||||||
chunkSize: 20_000,
|
chunkSize: 20_000,
|
||||||
metadata: {
|
metadata: {
|
||||||
assignmentId: id,
|
contestId: id,
|
||||||
filename: file.name,
|
filename: file.name,
|
||||||
contentType: file.type,
|
contentType: file.type,
|
||||||
fileTypeId: fileTypeId,
|
fileTypeId: fileTypeId,
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,8 @@ const LoginForm = () => {
|
||||||
Number(profile?.data?.data?.roleId) == 10 ||
|
Number(profile?.data?.data?.roleId) == 10 ||
|
||||||
Number(profile?.data?.data?.roleId) == 11 ||
|
Number(profile?.data?.data?.roleId) == 11 ||
|
||||||
Number(profile?.data?.data?.roleId) == 12 ||
|
Number(profile?.data?.data?.roleId) == 12 ||
|
||||||
Number(profile?.data?.data?.roleId) == 18
|
Number(profile?.data?.data?.roleId) == 18 ||
|
||||||
|
Number(profile?.data?.data?.roleId) == 19
|
||||||
) {
|
) {
|
||||||
if (profile?.data?.data?.roleId === 18) {
|
if (profile?.data?.data?.roleId === 18) {
|
||||||
window.location.href = "/in/dashboard/executive";
|
window.location.href = "/in/dashboard/executive";
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ const ProfileInfo = () => {
|
||||||
<div className="text-sm font-medium capitalize lg:block hidden">
|
<div className="text-sm font-medium capitalize lg:block hidden">
|
||||||
{detail?.fullname}
|
{detail?.fullname}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs">({detail?.fullname})</p>
|
<p className="text-xs">({detail?.username})</p>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-base me-2.5 lg:inline-block hidden">
|
<span className="text-base me-2.5 lg:inline-block hidden">
|
||||||
<Icon icon="heroicons-outline:chevron-down"></Icon>
|
<Icon icon="heroicons-outline:chevron-down"></Icon>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,285 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as React from "react"
|
||||||
|
import { ChevronsUpDown, Check, CirclePlus } from 'lucide-react';
|
||||||
|
|
||||||
|
import { cn, getCookiesDecrypt } from "@/lib/utils"
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
AvatarFallback,
|
||||||
|
AvatarImage,
|
||||||
|
} from "@/components/ui/avatar"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList,
|
||||||
|
CommandSeparator,
|
||||||
|
} from "@/components/ui/command"
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog"
|
||||||
|
import { Input } from "@/components/ui/input"
|
||||||
|
import { Label } from "@/components/ui/label"
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from "@/components/ui/popover"
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select"
|
||||||
|
import { useConfig } from "@/hooks/use-config";
|
||||||
|
import { useMediaQuery } from "@/hooks/use-media-query";
|
||||||
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
|
import { useMenuHoverConfig } from "@/hooks/use-menu-hover";
|
||||||
|
import { getInfoProfile } from "@/service/auth";
|
||||||
|
import { getUserRolePlacements, saveUserRolePlacements } from "@/service/management-user/management-user";
|
||||||
|
|
||||||
|
// var groups = [
|
||||||
|
// {
|
||||||
|
// label: "Wilayah Tugas",
|
||||||
|
// teams: [],
|
||||||
|
// },
|
||||||
|
// ]
|
||||||
|
|
||||||
|
// type Team = (typeof groups)[number]["teams"][number]
|
||||||
|
|
||||||
|
type PopoverTriggerProps = React.ComponentPropsWithoutRef<typeof PopoverTrigger>
|
||||||
|
|
||||||
|
interface TeamSwitcherProps extends PopoverTriggerProps { }
|
||||||
|
|
||||||
|
const scaleVariants = {
|
||||||
|
collapsed: { scale: 0.8 },
|
||||||
|
expanded: { scale: 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function TeamWorkspaceSwitcher({ className }: TeamSwitcherProps) {
|
||||||
|
const [config] = useConfig();
|
||||||
|
const [hoverConfig] = useMenuHoverConfig();
|
||||||
|
const { hovered } = hoverConfig;
|
||||||
|
const [detail, setDetail] = React.useState<any>();
|
||||||
|
const userId = getCookiesDecrypt("uie");
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const [showNewTeamDialog, setShowNewTeamDialog] = React.useState(false);
|
||||||
|
const [groups, setGroups] = React.useState<any>()
|
||||||
|
const [selectedTeam, setSelectedTeam] = React.useState<any>({ label: "", value: "" });
|
||||||
|
const isDesktop = useMediaQuery("(min-width: 1280px)")
|
||||||
|
if (config.showSwitcher === false || config.sidebar === 'compact') return null
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
async function initState() {
|
||||||
|
const response = await getInfoProfile();
|
||||||
|
const details = response?.data?.data;
|
||||||
|
|
||||||
|
setDetail(details);
|
||||||
|
console.log("data", details);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPlacement() {
|
||||||
|
const response = await getUserRolePlacements(Number(userId));
|
||||||
|
const data = response?.data?.data;
|
||||||
|
|
||||||
|
var placementArr: any[] = [];
|
||||||
|
data?.forEach((row: any) => {
|
||||||
|
placementArr.push({
|
||||||
|
label: row.roleName + " | " + row.userLevelName,
|
||||||
|
value: Number(row.id),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const groupsTemp = [
|
||||||
|
{
|
||||||
|
label: "Wilayah Tugas",
|
||||||
|
teams: placementArr,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
setGroups(groupsTemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
initState();
|
||||||
|
getPlacement();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={showNewTeamDialog} onOpenChange={setShowNewTeamDialog}>
|
||||||
|
<Popover open={open} onOpenChange={setOpen}>
|
||||||
|
|
||||||
|
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
key={(config.collapsed && !hovered) ? "collapsed" : "expanded"}
|
||||||
|
initial={{ scale: 0.9 }}
|
||||||
|
animate={{ scale: 1 }}
|
||||||
|
transition={{ type: "spring", stiffness: 300, damping: 20 }}
|
||||||
|
|
||||||
|
|
||||||
|
>
|
||||||
|
{(config.collapsed && !hovered) ? <Button
|
||||||
|
variant="outline"
|
||||||
|
color="secondary"
|
||||||
|
role="combobox"
|
||||||
|
fullWidth
|
||||||
|
aria-expanded={open}
|
||||||
|
aria-label="Select a team"
|
||||||
|
className={cn(" h-14 w-14 mx-auto p-0 md:p-0 dark:border-secondary ring-offset-sidebar", className)}
|
||||||
|
>
|
||||||
|
<Avatar className="">
|
||||||
|
<AvatarImage
|
||||||
|
height={24}
|
||||||
|
width={24}
|
||||||
|
// src={session?.user?.image as any}
|
||||||
|
alt={selectedTeam.label}
|
||||||
|
className="grayscale"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AvatarFallback>{detail?.username}</AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
</Button> : <Button
|
||||||
|
variant="outline"
|
||||||
|
color="secondary"
|
||||||
|
role="combobox"
|
||||||
|
fullWidth
|
||||||
|
aria-expanded={open}
|
||||||
|
aria-label="Select a team"
|
||||||
|
className={cn(" h-auto py-3 md:px-3 px-3 justify-start dark:border-secondary ring-offset-sidebar", className)}
|
||||||
|
>
|
||||||
|
<div className=" flex gap-2 flex-1 items-center">
|
||||||
|
<Avatar className=" flex-none h-[38px] w-[38px]">
|
||||||
|
{/* <AvatarImage
|
||||||
|
height={38}
|
||||||
|
width={38}
|
||||||
|
// src={session?.user?.image as any}
|
||||||
|
alt={selectedTeam.label}
|
||||||
|
className="grayscale"
|
||||||
|
/> */}
|
||||||
|
|
||||||
|
<AvatarFallback><p className="text-md uppercase">{detail?.username[0]}</p></AvatarFallback>
|
||||||
|
</Avatar>
|
||||||
|
<div className="flex-1 text-start w-[100px]">
|
||||||
|
|
||||||
|
<div className=" text-sm font-semibold text-default-900">{detail?.username}</div>
|
||||||
|
<div className=" text-xs font-normal text-default-500 dark:text-default-700 truncate ">{selectedTeam.label}</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="">
|
||||||
|
<ChevronsUpDown className="ml-auto h-5 w-5 shrink-0 text-default-500 dark:text-default-700" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Button>}
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="w-[200px] p-0">
|
||||||
|
<Command>
|
||||||
|
<CommandList>
|
||||||
|
<CommandInput placeholder="Search team..." className=" placeholder:text-xs" />
|
||||||
|
<CommandEmpty>No team found.</CommandEmpty>
|
||||||
|
{groups?.map((group: any) => (
|
||||||
|
<CommandGroup key={group.label} heading={group.label}>
|
||||||
|
{group.teams.map((team: any) => (
|
||||||
|
<CommandItem
|
||||||
|
key={team.value}
|
||||||
|
onSelect={() => {
|
||||||
|
setSelectedTeam(team)
|
||||||
|
setOpen(false)
|
||||||
|
}}
|
||||||
|
className="text-sm font-normal"
|
||||||
|
>
|
||||||
|
|
||||||
|
{team.label}
|
||||||
|
<Check
|
||||||
|
className={cn(
|
||||||
|
"ml-auto h-4 w-4",
|
||||||
|
selectedTeam.value === team.value
|
||||||
|
? "opacity-100"
|
||||||
|
: "opacity-0"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</CommandItem>
|
||||||
|
))}
|
||||||
|
</CommandGroup>
|
||||||
|
))}
|
||||||
|
</CommandList>
|
||||||
|
{/* <CommandSeparator /> */}
|
||||||
|
{/* <CommandList>
|
||||||
|
<CommandGroup>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<CommandItem
|
||||||
|
onSelect={() => {
|
||||||
|
setOpen(false)
|
||||||
|
setShowNewTeamDialog(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CirclePlus className="mr-2 h-5 w-5" />
|
||||||
|
Create Team
|
||||||
|
</CommandItem>
|
||||||
|
</DialogTrigger>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList> */}
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Create team</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Add a new team to manage products and customers.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div>
|
||||||
|
<div className="space-y-4 py-2 pb-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="name">Team name</Label>
|
||||||
|
<Input id="name" placeholder="Acme Inc." />
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="plan">Subscription plan</Label>
|
||||||
|
<Select>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a plan" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="free">
|
||||||
|
<span className="font-medium">Free</span> -{" "}
|
||||||
|
<span className="text-muted-foreground">
|
||||||
|
Trial for two weeks
|
||||||
|
</span>
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="pro">
|
||||||
|
<span className="font-medium">Pro</span> -{" "}
|
||||||
|
<span className="text-muted-foreground">
|
||||||
|
$9/month per user
|
||||||
|
</span>
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={() => setShowNewTeamDialog(false)}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button type="submit">Continue</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Ellipsis, LogOut } from "lucide-react";
|
import { Ellipsis, LogOut } from "lucide-react";
|
||||||
import { usePathname } from "@/components/navigation";
|
import { usePathname } from "@/components/navigation";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
||||||
import { getMenuList } from "@/lib/menus";
|
import { getMenuList } from "@/lib/menus";
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
import {
|
import {
|
||||||
|
|
@ -26,6 +26,7 @@ import Logo from '@/components/logo';
|
||||||
import SidebarHoverToggle from '@/components/partials/sidebar/sidebar-hover-toggle';
|
import SidebarHoverToggle from '@/components/partials/sidebar/sidebar-hover-toggle';
|
||||||
import { useMenuHoverConfig } from '@/hooks/use-menu-hover';
|
import { useMenuHoverConfig } from '@/hooks/use-menu-hover';
|
||||||
import { useMediaQuery } from '@/hooks/use-media-query';
|
import { useMediaQuery } from '@/hooks/use-media-query';
|
||||||
|
import TeamWorkspaceSwitcher from '../common/team-workspace-switcher';
|
||||||
|
|
||||||
|
|
||||||
export function MenuClassic({ }) {
|
export function MenuClassic({ }) {
|
||||||
|
|
@ -36,7 +37,7 @@ export function MenuClassic({ }) {
|
||||||
const direction = getLangDir(params?.locale ?? '');
|
const direction = getLangDir(params?.locale ?? '');
|
||||||
|
|
||||||
const isDesktop = useMediaQuery('(min-width: 1280px)')
|
const isDesktop = useMediaQuery('(min-width: 1280px)')
|
||||||
|
const userRoleId = getCookiesDecrypt("urie");
|
||||||
|
|
||||||
const menuList = getMenuList(pathname, t);
|
const menuList = getMenuList(pathname, t);
|
||||||
const [config, setConfig] = useConfig()
|
const [config, setConfig] = useConfig()
|
||||||
|
|
@ -71,17 +72,16 @@ export function MenuClassic({ }) {
|
||||||
|
|
||||||
|
|
||||||
<ScrollArea className="[&>div>div[style]]:!block" dir={direction}>
|
<ScrollArea className="[&>div>div[style]]:!block" dir={direction}>
|
||||||
{/* {isDesktop && (
|
{isDesktop && Number(userRoleId) == 19 ? (
|
||||||
<div className={cn(' space-y-3 mt-6 ', {
|
<div className={cn(' space-y-3 mt-6 ', {
|
||||||
'px-4': !collapsed || hovered,
|
'px-4': !collapsed || hovered,
|
||||||
'text-center': collapsed || !hovered
|
'text-center': collapsed || !hovered
|
||||||
})}>
|
})}>
|
||||||
|
<TeamWorkspaceSwitcher />
|
||||||
<TeamSwitcher />
|
{/* <SearchBar /> */}
|
||||||
<SearchBar />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
)} */}
|
) : ""}
|
||||||
|
|
||||||
<nav className="mt-4 h-full w-full">
|
<nav className="mt-4 h-full w-full">
|
||||||
<ul className=" h-full flex flex-col min-h-[calc(100vh-48px-36px-16px-32px)] lg:min-h-[calc(100vh-32px-40px-32px)] items-start space-y-1 px-4">
|
<ul className=" h-full flex flex-col min-h-[calc(100vh-48px-36px-16px-32px)] lg:min-h-[calc(100vh-32px-40px-32px)] items-start space-y-1 px-4">
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Router } from "next/router";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
|
|
||||||
|
|
@ -29,7 +30,7 @@ export function error(msg: string): void {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function success(redirect: string): void {
|
export function success(router: Router, redirect: string): void {
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
title: '<p class="text-green-600 font-bold">Sukses</p>',
|
title: '<p class="text-green-600 font-bold">Sukses</p>',
|
||||||
icon: "success",
|
icon: "success",
|
||||||
|
|
@ -38,7 +39,7 @@ export function success(redirect: string): void {
|
||||||
allowOutsideClick: false,
|
allowOutsideClick: false,
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
window.location.href = redirect;
|
router.push(redirect);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2661,7 +2661,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
} else if (Number(roleId) == 11) {
|
} else if (Number(roleId) == 11 || Number(roleId) == 19) {
|
||||||
menusSelected = [
|
menusSelected = [
|
||||||
{
|
{
|
||||||
groupLabel: t("apps"),
|
groupLabel: t("apps"),
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ const axiosInterceptorInstance = axios.create({
|
||||||
// Request interceptor
|
// Request interceptor
|
||||||
axiosInterceptorInstance.interceptors.request.use(
|
axiosInterceptorInstance.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
console.log("Config interceptor : ", config);
|
|
||||||
const accessToken = Cookies.get("access_token");
|
const accessToken = Cookies.get("access_token");
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
if (config.headers)
|
if (config.headers)
|
||||||
|
|
|
||||||
|
|
@ -30,16 +30,32 @@ export async function getListSchools() {
|
||||||
const url = "users/user-schools/list";
|
const url = "users/user-schools/list";
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getListCompetencies() {
|
export async function getListCompetencies() {
|
||||||
const url = "users/user-competencies/list";
|
const url = "users/user-competencies/list";
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getListExperiences() {
|
||||||
|
const url = "users/user-experiences/list";
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function saveUserInternal(data: any) {
|
export async function saveUserInternal(data: any) {
|
||||||
const url = "users/save";
|
const url = "users/save";
|
||||||
return httpPostInterceptor(url, data);
|
return httpPostInterceptor(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function saveUserRolePlacements(data: any) {
|
||||||
|
const url = "users/role-placements";
|
||||||
|
return httpPostInterceptor(url, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUserRolePlacements(userId: number) {
|
||||||
|
const url = `users/role-placements?userId=${userId}`;
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function getUserById(id: string) {
|
export async function getUserById(id: string) {
|
||||||
const url = `users?id=${id}`;
|
const url = `users?id=${id}`;
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue