feat: slicing kamus page

This commit is contained in:
mphstar 2024-12-22 19:06:20 +07:00
parent e444361026
commit b28e4eae68
32 changed files with 131 additions and 7 deletions

48
package-lock.json generated
View File

@ -15,6 +15,8 @@
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"react-router-dom": "^6.26.1",
"react-virtualized-auto-sizer": "^1.0.24",
"react-window": "^1.8.10",
"tailwind-merge": "^2.5.2",
"zustand": "^4.5.5"
},
@ -298,6 +300,22 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/runtime": {
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/runtime/node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
"node_modules/@babel/template": {
"version": "7.25.0",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz",
@ -3225,6 +3243,11 @@
"yallist": "^3.0.2"
}
},
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@ -3808,6 +3831,31 @@
"react-dom": ">=16.8"
}
},
"node_modules/react-virtualized-auto-sizer": {
"version": "1.0.24",
"resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.24.tgz",
"integrity": "sha512-3kCn7N9NEb3FlvJrSHWGQ4iVl+ydQObq2fHMn12i5wbtm74zHOPhz/i64OL3c1S1vi9i2GXtZqNqUJTQ+BnNfg==",
"peerDependencies": {
"react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0",
"react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-window": {
"version": "1.8.10",
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.10.tgz",
"integrity": "sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==",
"dependencies": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
},
"engines": {
"node": ">8.0.0"
},
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",

View File

@ -17,6 +17,8 @@
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"react-router-dom": "^6.26.1",
"react-virtualized-auto-sizer": "^1.0.24",
"react-window": "^1.8.10",
"tailwind-merge": "^2.5.2",
"zustand": "^4.5.5"
},

BIN
public/assets/kamus/a.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
public/assets/kamus/b.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
public/assets/kamus/c.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
public/assets/kamus/d.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
public/assets/kamus/e.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
public/assets/kamus/f.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
public/assets/kamus/g.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
public/assets/kamus/h.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
public/assets/kamus/i.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
public/assets/kamus/k.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
public/assets/kamus/l.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
public/assets/kamus/m.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
public/assets/kamus/n.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
public/assets/kamus/o.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
public/assets/kamus/p.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
public/assets/kamus/q.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
public/assets/kamus/r.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
public/assets/kamus/s.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
public/assets/kamus/t.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
public/assets/kamus/u.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
public/assets/kamus/v.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
public/assets/kamus/w.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
public/assets/kamus/x.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
public/assets/kamus/y.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@ -1,5 +1,6 @@
import { lazy, Suspense } from "react";
import { Route, Routes } from "react-router-dom";
import Kamus from "./pages/Kamus";
const Home = lazy(() => import("@/pages/Home"));
@ -15,7 +16,14 @@ const App = () => {
</Suspense>
}
/>
<Route path="/kamus" element={<div>Kamus</div>} />
<Route
path="/kamus"
element={
<Suspense fallback={<div>Loading...</div>}>
<Kamus />
</Suspense>
}
/>
</Route>
</Routes>
);

View File

@ -7,7 +7,7 @@ import NavLink from "../molecules/NavLink";
const HeaderPage = () => {
const navStore = useNavbarStore();
return (
<div className="bg-white drop-shadow w-full h-fit sticky top-0">
<div className="bg-white drop-shadow w-full h-fit sticky top-0 z-[300]">
<header className="flex flex-row items-center gap-2 justify-between px-4 py-3 container max-w-[1200px]">
<div className="flex gap-1 items-center">
<img
@ -22,7 +22,7 @@ const HeaderPage = () => {
</div>
<ul
className={cn(
"flex md:flex-row flex-col items-center justify-center fixed md:static min-h-svh md:min-h-0 w-full md:w-fit bg-white/50 md:bg-transparent md:backdrop-blur-none backdrop-blur-md z-[200] top-0 left-0",
"flex md:flex-row flex-col items-center justify-center fixed md:static min-h-svh md:min-h-0 w-full md:w-fit bg-white/50 md:bg-transparent md:backdrop-blur-none backdrop-blur-md z-[999] top-0 left-0",
navStore.isOpen ? "translate-y-0" : "-translate-y-full",
"duration-300 ease-in-out md:translate-y-0"
)}
@ -33,9 +33,21 @@ const HeaderPage = () => {
>
<IoClose />
</div>
<NavLink href="/" name="Home" isActive={true} />
<NavLink href="/kamus" name="Kamus" isActive={false} />
<NavLink href="/" name="Kuis" isActive={false} />
<NavLink
href="/"
name="Home"
isActive={navStore.navSelected === "home"}
/>
<NavLink
href="/kamus"
name="Kamus"
isActive={navStore.navSelected === "kamus"}
/>
<NavLink
href="/"
name="Kuis"
isActive={navStore.navSelected === "kuis"}
/>
</ul>
<button
onClick={() => navStore.toggle()}

View File

@ -6,6 +6,7 @@ import { FilesetResolver, HandLandmarker } from "@mediapipe/tasks-vision";
import calcLandmarkList from "@/utils/CalculateLandmark";
import preProcessLandmark from "@/utils/PreProcessLandmark";
import ConvertResult from "@/utils/ConvertResult";
import useNavbarStore from "@/stores/NavbarStore";
type PredictResult = {
abjad: String;
@ -130,11 +131,19 @@ const Home = () => {
requestAnimationFrame(detectHands);
};
const store = useNavbarStore();
useEffect(() => {
store.setNavSelected("home");
loadModel();
startWebcam();
setLoadCamera(true);
return () => {
// stop camera
};
}, []);
return (

41
src/pages/Kamus.tsx Normal file
View File

@ -0,0 +1,41 @@
import LayoutPage from "@/components/templates/LayoutPage";
import useNavbarStore from "@/stores/NavbarStore";
import { abjads } from "@/utils/ConvertResult";
import { useEffect } from "react";
const Kamus = () => {
const store = useNavbarStore();
useEffect(() => {
store.setNavSelected("kamus");
}, []);
return (
<LayoutPage>
<div className="flex flex-col flex-1 py-4">
<h1 className="font-semibold">Kamus SIBI</h1>
<div className="grid grid-cols-2 md:grid-cols-4 gap-6 mt-6">
{abjads.map((abjad, index) => (
<CardKamus
key={index}
title={`Abjad ${abjad.toLocaleUpperCase()}`}
image={`/assets/kamus/${abjad.toLocaleLowerCase()}.jpg`}
/>
))}
</div>
</div>
</LayoutPage>
);
};
const CardKamus = ({ title, image }: { title: string; image: string }) => {
return (
<div className="flex flex-col rounded-md bg-base-100 shadow-lg overflow-hidden">
<img className="h-[250px] object-cover" src={image} alt="Kamus SIBI" />
<div className="p-3 flex items-center justify-center font-semibold">
<p>{title}</p>
</div>
</div>
);
};
export default Kamus;

View File

@ -3,11 +3,15 @@ import { create } from "zustand";
type NavbarType = {
isOpen: boolean;
toggle: () => void;
navSelected: "home" | "kamus" | "kuis";
setNavSelected: (nav: "home" | "kamus" | "kuis") => void;
};
const useNavbarStore = create<NavbarType>((set) => ({
isOpen: false,
toggle: () => set((state) => ({ isOpen: !state.isOpen })),
navSelected: "home",
setNavSelected: (nav) => set({ navSelected: nav }),
}));
export default useNavbarStore;

View File

@ -1,4 +1,4 @@
const abjads = [
export const abjads = [
"A",
"B",
"C",