added grouping creator
All checks were successful
backend-action / build-image (push) Successful in 1m5s
All checks were successful
backend-action / build-image (push) Successful in 1m5s
This commit is contained in:
73
app/grouping/GroupCreator.tsx
Normal file
73
app/grouping/GroupCreator.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
"use client";
|
||||
|
||||
import { LocationContext } from "@/components/locationContenxt";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import Grouping from "./Grouping";
|
||||
import { unique } from "drizzle-orm/mysql-core";
|
||||
|
||||
type Props = {
|
||||
allJobs: JobCategory[];
|
||||
};
|
||||
|
||||
export type JobCategory = {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
type Group = {
|
||||
id: number;
|
||||
jobs: number[];
|
||||
};
|
||||
export default function GroupCreator({ allJobs }: Props) {
|
||||
let locationContext = useContext(LocationContext);
|
||||
let [usedJobs, setUsedJobs] = useState<number[]>([]);
|
||||
let [groups, setGroup] = useState<Group[]>(
|
||||
[...Array(4).keys()].map((i) => ({ id: i + 1, jobs: [] }))
|
||||
);
|
||||
function useJob(id: number) {
|
||||
setUsedJobs((u) => [...u, id]);
|
||||
}
|
||||
|
||||
function freeJob(id: number) {
|
||||
setUsedJobs((u) => u.filter((j) => j != id));
|
||||
}
|
||||
|
||||
function updateGroup(id: number, jobs: number[]) {
|
||||
setGroup((groups) =>
|
||||
groups.map((g) => {
|
||||
if (g.id != id) return g;
|
||||
else return { id, jobs };
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log(groups);
|
||||
}, [groups]);
|
||||
|
||||
if (
|
||||
locationContext?.zone[0] == undefined ||
|
||||
locationContext?.province[0] == undefined
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{groups.map((g) => (
|
||||
<div className="flex flex-col items-center" key={g.id}>
|
||||
<p>สายที่: {g.id}</p>
|
||||
<Grouping
|
||||
availableJobs={allJobs.filter((j) => !usedJobs.includes(j.id))}
|
||||
selectJob={useJob}
|
||||
removeJob={freeJob}
|
||||
updateGroup={(ids) => updateGroup(g.id, ids)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="flex justify-center">
|
||||
<button className="bg-green-300 rounded-md p-2">ยืนยัน</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
59
app/grouping/Grouping.tsx
Normal file
59
app/grouping/Grouping.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { JobCategory } from "./GroupCreator";
|
||||
|
||||
type Props = {
|
||||
availableJobs: JobCategory[];
|
||||
selectJob: (id: number) => void;
|
||||
removeJob: (id: number) => void;
|
||||
updateGroup: (id: number[]) => void;
|
||||
};
|
||||
|
||||
export default function Grouping({
|
||||
availableJobs,
|
||||
selectJob,
|
||||
removeJob,
|
||||
updateGroup,
|
||||
}: Props) {
|
||||
let [selectedJob, setSelectedJob] = useState<JobCategory[]>([]);
|
||||
function addJob(id: string) {
|
||||
let _id = parseInt(id);
|
||||
let job = availableJobs.find((j) => j.id == _id);
|
||||
if (job == undefined) return;
|
||||
setSelectedJob((old) => [...old, job]);
|
||||
selectJob(_id);
|
||||
}
|
||||
function removeJobFromGroup(id: number) {
|
||||
setSelectedJob((old) => old.filter((j) => j.id != id));
|
||||
removeJob(id);
|
||||
}
|
||||
useEffect(() => {
|
||||
updateGroup(selectedJob.map((j) => j.id));
|
||||
}, [selectedJob]);
|
||||
return (
|
||||
<div className="flex flex-col gap-2 m-2 p-2 border-black rounded-md shadow-md border w-full">
|
||||
{selectedJob.map((j) => (
|
||||
<div className="flex justify-between gap-2 p-2" key={j.id}>
|
||||
<p>{j.name}</p>
|
||||
<button
|
||||
onClick={() => removeJobFromGroup(j.id)}
|
||||
className="text-red-400"
|
||||
>
|
||||
นำออก
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
{selectedJob.length < 5 && (
|
||||
<select onChange={(e) => addJob(e.currentTarget.value)}>
|
||||
<option value={undefined} hidden>
|
||||
None
|
||||
</option>
|
||||
{availableJobs.map((j) => (
|
||||
<option value={j.id} key={j.id}>
|
||||
{j.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
import { db } from "@/src/db";
|
||||
import LocationSelector from "../../components/LocationSelector";
|
||||
import LocationContextProvider from "@/components/locationContenxt";
|
||||
import GroupCreator from "./GroupCreator";
|
||||
|
||||
export default async function Page() {
|
||||
let provinces = await db.query.province
|
||||
.findMany({ with: { zones: true } })
|
||||
.execute();
|
||||
let jobList = await db.query.group.findMany().execute();
|
||||
return (
|
||||
<LocationContextProvider>
|
||||
<LocationSelector provinces={provinces} />
|
||||
<GroupCreator allJobs={jobList} />
|
||||
</LocationContextProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,11 @@ export default function RootLayout({
|
||||
}) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
<body>
|
||||
<div className="container mx-auto mt-2">{children}</div>
|
||||
<div className="container mx-auto mt-2 p-2">{children}</div>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@@ -46,30 +46,42 @@ export default function LocationSelector({ provinces }: Props) {
|
||||
}, [amphurId]);
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex gap-2">
|
||||
จังหวัด:
|
||||
<select
|
||||
value={provinceId}
|
||||
className="flex-1"
|
||||
onChange={(e) => setProvince(e.currentTarget.value)}
|
||||
>
|
||||
<option value={undefined}>None</option>
|
||||
<option value={undefined} hidden>
|
||||
None
|
||||
</option>
|
||||
{provinces.map((p) => (
|
||||
<option key={p.id} value={p.id}>
|
||||
{p.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{amphurList && (
|
||||
<div className="flex gap-2">
|
||||
อำเภอ:
|
||||
<select
|
||||
value={amphurId}
|
||||
className="flex-1"
|
||||
onChange={(e) => setAmphur(e.currentTarget.value)}
|
||||
>
|
||||
<option value={undefined}>None</option>
|
||||
<option value={undefined} hidden>
|
||||
None
|
||||
</option>
|
||||
{amphurList.map((a) => (
|
||||
<option key={a.id} value={a.id}>
|
||||
{a.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user