Skip to content

Commit

Permalink
Merge pull request #89 from reacto11mecha/question-eligibility
Browse files Browse the repository at this point in the history
Menambahkan status kelayakan pengerjaan soal
  • Loading branch information
reacto11mecha authored Feb 10, 2025
2 parents eba7f7f + 512c634 commit f5f6d83
Show file tree
Hide file tree
Showing 46 changed files with 4,551 additions and 107 deletions.
29 changes: 27 additions & 2 deletions .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ on:
- main

jobs:
build:
build-admin:
if: github.repository == 'reacto11mecha/enpitsu'

runs-on: ubuntu-latest

steps:
Expand All @@ -30,3 +30,28 @@ jobs:
file: "./apps/admin/Dockerfile"
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/enpitsu:${{ github.ref_name }}

build-processor:
if: github.repository == 'reacto11mecha/enpitsu'

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build the Docker image
uses: docker/build-push-action@v5
with:
context: .
file: "./apps/processor/Dockerfile"
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/enpitsu-processor:${{ github.ref_name }}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,6 @@ yarn-error.log*
# turbo
.turbo

.cache
.cache

*.log
2 changes: 1 addition & 1 deletion apps/admin/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const config = {
"@enpitsu/api",
"@enpitsu/auth",
"@enpitsu/db",
"@enpitsu/cache",
"@enpitsu/redis",
],

output: "standalone",
Expand Down
4 changes: 2 additions & 2 deletions apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"dependencies": {
"@enpitsu/api": "workspace:^0.1.0",
"@enpitsu/auth": "workspace:^0.1.0",
"@enpitsu/cache": "workspace:^0.1.0",
"@enpitsu/db": "workspace:^0.1.0",
"@enpitsu/redis": "workspace:^0.1.0",
"@enpitsu/token-generator": "workspace:^0.1.0",
"@enpitsu/ui": "workspace:^0.1.0",
"@tanstack/react-query": "catalog:",
Expand Down Expand Up @@ -59,7 +59,7 @@
"@types/react": "catalog:react18",
"@types/react-dom": "catalog:react18",
"@types/string-similarity": "^4.0.2",
"dotenv-cli": "^7.3.0",
"dotenv-cli": "^7.4.4",
"eslint": "catalog:",
"jiti": "^2.4.2",
"prettier": "catalog:",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ export const ChoiceEditor = memo(function ChoiceEditorConstructor({
specificChoiceQuery.error,
form,
optionsField.update,
toast,
]);

const specificChoiceMutation = api.question.updateSpecificChoice.useMutation({
Expand Down Expand Up @@ -157,6 +156,7 @@ export const ChoiceEditor = memo(function ChoiceEditorConstructor({
async onSettled() {
// Sync with server once mutation has settled
await utils.question.getSpecificChoiceQuestion.invalidate();
await utils.question.getEligibleStatusFromQuestion.invalidate();
},
});

Expand Down Expand Up @@ -193,6 +193,7 @@ export const ChoiceEditor = memo(function ChoiceEditorConstructor({
async onSettled() {
// Sync with server once mutation has settled
await utils.question.getChoicesIdByQuestionId.invalidate({ questionId });
await utils.question.getEligibleStatusFromQuestion.invalidate();
},
});

Expand All @@ -219,7 +220,7 @@ export const ChoiceEditor = memo(function ChoiceEditorConstructor({

return (
<Form {...form}>
<Card>
<Card id={`choice-iqid-${choiceIqid}`}>
<CardHeader>
<CardTitle>Soal Nomor {questionNo}</CardTitle>
<CardDescription className="text-muted-foreground">
Expand Down
204 changes: 204 additions & 0 deletions apps/admin/src/_components/Soal/QuestionItems/EligibleStatus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import type { RouterOutputs } from "@enpitsu/api";
import { memo, useMemo, useState } from "react";
import { cn } from "@enpitsu/ui";
import { Button } from "@enpitsu/ui/button";
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@enpitsu/ui/sheet";
import {
LaptopMinimalCheck,
Loader2,
LoaderPinwheel,
OctagonX,
} from "lucide-react";

interface Props {
isPending: boolean;
isError: boolean;
data: RouterOutputs["question"]["getEligibleStatusFromQuestion"] | undefined;
}

export const EligibleStatus = memo(function EligibleStatus({
isPending,
isError,
data,
}: Props) {
const [sheetOpened, setOpened] = useState(false);

const currentStatus = useMemo(() => {
if (isPending)
return {
readable: "Sedang mengambil data status ke server...",
showReason: false,
};
if (isError)
return {
readable: "Gagal mengambil data status ke server.",
showReason: false,
};

if (!data)
return {
readable: "Status data kosong, mohon menunggu...",
showReason: false,
};

switch (data.eligible) {
case "ELIGIBLE":
return {
readable: "Status aman, peserta dapat mengerjakan soal ini.",
showReason: false,
};
case "PROCESSING":
return {
readable: "Sedang dilakukan pengecekan...",
showReason: false,
};
case "NOT_ELIGIBLE":
default:
return { readable: "Soal tidak layak dikerjakan.", showReason: true };
}
}, [isPending, isError, data]);

return (
<div className="w-full md:fixed md:bottom-2 md:right-2 md:w-fit">
<Sheet
open={sheetOpened}
onOpenChange={() => {
setOpened((prev) => !prev);
}}
>
<SheetTrigger asChild>
<Button
variant={isError ? "destructive" : "default"}
className="h-10 w-full md:w-fit"
>
{isPending ? (
<Loader2 className="!h-7 !w-7 animate-spin" />
) : data?.eligible === "NOT_ELIGIBLE" || isError ? (
<OctagonX
className={cn(
"!h-7 !w-7",
!isError && "text-red-500 dark:text-red-700",
)}
/>
) : data?.eligible === "PROCESSING" ? (
<LoaderPinwheel className="!h-7 !w-7 animate-spin" />
) : (
<LaptopMinimalCheck className="!h-7 !w-7 text-green-500 dark:text-green-700" />
)}
</Button>
</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Status Kelayakan Pengerjaan Soal</SheetTitle>
<SheetDescription className="text-justify">
Soal dapat dikatakan layak untuk dikerjakan oleh peserta apabila
terdapat soal pilihan ganda atau soal esai atau ada keduanya.
Setiap soal wajib memiliki pertanyaan dan opsi jawaban. Pada
bagian ini, anda dapat mengetahui kesalahan yang anda dapat
perbaiki.
</SheetDescription>

<p className="mt-2 text-wrap text-sm">
Status saat ini: {currentStatus.readable}
</p>

{currentStatus.showReason ? (
<p className="text-pretty text-sm">
Alasan: {data?.notEligibleReason ?? "N/A"}
</p>
) : null}

{currentStatus.showReason && data?.detailedNotEligible ? (
<div className="mt-12 flex max-h-[55vh] flex-col gap-5 overflow-y-auto pb-14">
{data.detailedNotEligible.some(
(detail) => detail.type === "choice",
) ? (
<div className="space-y-2">
<p className="text-wrap text-base">
Kesalahan Pada Pilihan Ganda
</p>

<ul className="list-disc space-y-1.5 pl-5">
{data.detailedNotEligible
.filter((d) => d.type === "choice")
.map((d) => (
<li className="text-pretty text-sm" key={d.iqid}>
<button
className="underline"
onClick={() => {
const el = document.querySelector(
`#choice-iqid-${d.iqid}`,
);

if (el) {
setOpened(false);

setTimeout(
() =>
el.scrollIntoView({ behavior: "smooth" }),
585,
);
}
}}
>
KE SOAL
</button>{" "}
| {d.errorMessage}
</li>
))}
</ul>
</div>
) : null}

{data.detailedNotEligible.some(
(detail) => detail.type === "essay",
) ? (
<div className="space-y-2">
<p className="text-wrap text-base">Kesalahan Pada Esai</p>

<ul className="list-disc space-y-1.5 pl-5">
{data.detailedNotEligible
.filter((d) => d.type === "essay")
.map((d) => (
<li className="text-pretty text-sm" key={d.iqid}>
<button
className="underline"
onClick={() => {
const el = document.querySelector(
`#essay-iqid-${d.iqid}`,
);

if (el) {
setOpened(false);

setTimeout(
() =>
el.scrollIntoView({ behavior: "smooth" }),
585,
);
}
}}
>
KE SOAL
</button>{" "}
| {d.errorMessage}
</li>
))}
</ul>
</div>
) : null}
</div>
) : null}
</SheetHeader>
</SheetContent>
</Sheet>
</div>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export const EssayEditor = memo(function EssayEditorConstructor({
async onSettled() {
// Sync with server once mutation has settled
await utils.question.getSpecificEssayQuestion.invalidate();
await utils.question.getEligibleStatusFromQuestion.invalidate();
},
});

Expand Down Expand Up @@ -168,6 +169,7 @@ export const EssayEditor = memo(function EssayEditorConstructor({
async onSettled() {
// Sync with server once mutation has settled
await utils.question.getEssaysIdByQuestionId.invalidate({ questionId });
await utils.question.getEligibleStatusFromQuestion.invalidate();
},
});

Expand All @@ -194,7 +196,7 @@ export const EssayEditor = memo(function EssayEditorConstructor({

return (
<Form {...form}>
<Card>
<Card id={`essay-iqid-${essayIqid}`}>
<CardHeader>
<CardTitle>Esai Nomor {questionNo}</CardTitle>
<CardDescription className="text-muted-foreground">
Expand Down
Loading

0 comments on commit f5f6d83

Please sign in to comment.