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 { db } from "@/src/db";
|
||||||
import LocationSelector from "../../components/LocationSelector";
|
import LocationSelector from "../../components/LocationSelector";
|
||||||
import LocationContextProvider from "@/components/locationContenxt";
|
import LocationContextProvider from "@/components/locationContenxt";
|
||||||
|
import GroupCreator from "./GroupCreator";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
let provinces = await db.query.province
|
let provinces = await db.query.province
|
||||||
.findMany({ with: { zones: true } })
|
.findMany({ with: { zones: true } })
|
||||||
.execute();
|
.execute();
|
||||||
|
let jobList = await db.query.group.findMany().execute();
|
||||||
return (
|
return (
|
||||||
<LocationContextProvider>
|
<LocationContextProvider>
|
||||||
<LocationSelector provinces={provinces} />
|
<LocationSelector provinces={provinces} />
|
||||||
|
<GroupCreator allJobs={jobList} />
|
||||||
</LocationContextProvider>
|
</LocationContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,11 @@ export default function RootLayout({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div className="container mx-auto mt-2">{children}</div>
|
<div className="container mx-auto mt-2 p-2">{children}</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -46,30 +46,42 @@ export default function LocationSelector({ provinces }: Props) {
|
|||||||
}, [amphurId]);
|
}, [amphurId]);
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<select
|
<div className="flex gap-2">
|
||||||
value={provinceId}
|
จังหวัด:
|
||||||
onChange={(e) => setProvince(e.currentTarget.value)}
|
|
||||||
>
|
|
||||||
<option value={undefined}>None</option>
|
|
||||||
{provinces.map((p) => (
|
|
||||||
<option key={p.id} value={p.id}>
|
|
||||||
{p.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
{amphurList && (
|
|
||||||
<select
|
<select
|
||||||
value={amphurId}
|
value={provinceId}
|
||||||
onChange={(e) => setAmphur(e.currentTarget.value)}
|
className="flex-1"
|
||||||
|
onChange={(e) => setProvince(e.currentTarget.value)}
|
||||||
>
|
>
|
||||||
<option value={undefined}>None</option>
|
<option value={undefined} hidden>
|
||||||
{amphurList.map((a) => (
|
None
|
||||||
<option key={a.id} value={a.id}>
|
</option>
|
||||||
{a.name}
|
{provinces.map((p) => (
|
||||||
|
<option key={p.id} value={p.id}>
|
||||||
|
{p.name}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{amphurList && (
|
||||||
|
<div className="flex gap-2">
|
||||||
|
อำเภอ:
|
||||||
|
<select
|
||||||
|
value={amphurId}
|
||||||
|
className="flex-1"
|
||||||
|
onChange={(e) => setAmphur(e.currentTarget.value)}
|
||||||
|
>
|
||||||
|
<option value={undefined} hidden>
|
||||||
|
None
|
||||||
|
</option>
|
||||||
|
{amphurList.map((a) => (
|
||||||
|
<option key={a.id} value={a.id}>
|
||||||
|
{a.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user