diff options
Diffstat (limited to 'app/page.tsx')
| -rw-r--r-- | app/page.tsx | 128 |
1 files changed, 63 insertions, 65 deletions
diff --git a/app/page.tsx b/app/page.tsx index 07a89f1..6a1da90 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -14,41 +14,49 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { getAuth } from "./lib/api/auth"; -// ====== ROLE EMAIL LISTS ====== +type AuthLike = { email?: string; token?: string } | string | null; + const DRIVER_EMAILS = new Set( - ["driverindoteknik@gmail.com", "sulistianaridwan8@gmail.com"] - .map(e => e.toLowerCase()) + ["driverindoteknik@gmail.com", "it@fixcomart.co.id", "sulistianaridwan8@gmail.com"].map( + (e) => e.toLowerCase() + ) ); - const DISPATCH_EMAILS = new Set( - ["rahmat.afiudin@gmail.com", "it@fixcomart.co.id"] - .map(e => e.toLowerCase()) + ["rahmat.afiudin@gmail.com", "it@fixcomart.co.id"].map((e) => e.toLowerCase()) ); -function extractEmailFromAuth(auth: unknown): string | null { - if (auth && typeof auth === "object" && "email" in (auth as any)) { - const email = (auth as any).email; - if (typeof email === "string") return email; +function extractEmailFromAuth(auth: AuthLike): string | null { + // object with email + if (auth && typeof auth === "object" && "email" in auth && typeof auth.email === "string") { + return auth.email; } - if (auth && typeof auth === "object" && "token" in (auth as any)) { - const t = (auth as any).token; - if (typeof t === "string") { - const parts = t.split("."); - if (parts.length === 3) { - try { - const payload = JSON.parse(atob(parts[1])); - return payload?.email ?? payload?.preferred_username ?? payload?.sub ?? null; - } catch {} + // object with token (JWT) + if (auth && typeof auth === "object" && "token" in auth && typeof auth.token === "string") { + const t = auth.token; + const parts = t.split("."); + if (parts.length === 3) { + try { + const payload = JSON.parse(atob(parts[1])); + const email: unknown = + payload?.email ?? payload?.preferred_username ?? payload?.sub ?? null; + return typeof email === "string" ? email : null; + } catch { + return null; } } } + // JWT string if (typeof auth === "string") { const parts = auth.split("."); if (parts.length === 3) { try { const payload = JSON.parse(atob(parts[1])); - return payload?.email ?? payload?.preferred_username ?? payload?.sub ?? null; - } catch {} + const email: unknown = + payload?.email ?? payload?.preferred_username ?? payload?.sub ?? null; + return typeof email === "string" ? email : null; + } catch { + return null; + } } } return null; @@ -74,21 +82,15 @@ export default function Home() { const router = useRouter(); useEffect(() => { - const token = getAuth(); - console.log("FE auth (akan dipakai untuk header Token):", token); - + const token = getAuth() as AuthLike; if (!token) { router.push("/login"); } else { setIsLogin(true); - const email = extractEmailFromAuth(token); const lower = (email ?? "").toLowerCase(); - - // PRIORITAS: dispatch > driver const dispatchFlag = DISPATCH_EMAILS.has(lower); const driverFlag = DRIVER_EMAILS.has(lower) && !dispatchFlag; - setIsDispatch(dispatchFlag); setIsDriver(driverFlag); } @@ -98,7 +100,6 @@ export default function Home() { event.preventDefault(); setIsLoading(true); - // Hanya role dispatch yang wajib foto Dispatch const needDispatch = isDispatch; if (!barcode || !imageSj || !imagePackage || (needDispatch && !imageDispatch)) { @@ -114,9 +115,12 @@ export default function Home() { try { const newSjImage = imageSj.replace(/^.*?,/, ""); const newPackageImage = imagePackage.replace(/^.*?,/, ""); - const newDispatchImage = imageDispatch ? imageDispatch.replace(/^.*?,/, "") : undefined; + const newDispatchImage = + imageDispatch && imageDispatch.startsWith("data:") + ? imageDispatch.replace(/^.*?,/, "") + : undefined; - const data: any = { + const data: Record<string, string> = { sj_document: newSjImage, paket_document: newPackageImage, }; @@ -124,28 +128,24 @@ export default function Home() { data.dispatch_document = newDispatchImage; } - const response = await odooApi( + const response = (await odooApi( "PUT", `/api/v1/stock-picking/${barcode}/documentation`, data - ); + )) as { status: { code: number } }; - if (response.status.code == 200) { + if (response?.status?.code === 200) { alert("Berhasil Submit Data"); setBarcode(""); setImageSj(""); setImagePackage(""); setImageDispatch(""); - setIsLoading(false); - } else if (response.status.code == 404) { + } else if (response?.status?.code === 404) { alert("Gagal Submit Data, Picking Code Tidak Ditemukan "); - setIsLoading(false); } else { alert("Gagal Submit Data, Silahkan Coba Lagi"); - setIsLoading(false); } - return response.data; - } catch (error: unknown) { + } catch (error) { if (error instanceof Error) { console.error("Error mengirim data:", error.message); } else if (axios.isAxiosError(error)) { @@ -153,6 +153,7 @@ export default function Home() { } else { console.error("Unknown error:", error); } + } finally { setIsLoading(false); } }; @@ -166,14 +167,13 @@ export default function Home() { <div> <BarcodeScanner /> </div> - <div className="h-4"></div> - + <div className="h-4" /> <div className="flex justify-between"> <SjCamera /> <PackageCamera /> - {!isDriver && <DispatchCamera />} {/* disembunyikan untuk driver */} + {!isDriver && <DispatchCamera />} </div> - <div className="h-2"></div> + <div className="h-2" /> {imageSj && ( <> @@ -184,16 +184,16 @@ export default function Home() { <Image src={imageSj} alt="Captured" - layout="fill" - objectFit="cover" + fill unoptimized className="p-2" + style={{ objectFit: "cover" }} /> </div> </> )} - <div className="h-2"></div> + <div className="h-2" /> {imagePackage && ( <> @@ -204,16 +204,16 @@ export default function Home() { <Image src={imagePackage} alt="Captured" - layout="fill" - objectFit="cover" + fill unoptimized className="p-2" + style={{ objectFit: "cover" }} /> </div> </> )} - <div className="h-2"></div> + <div className="h-2" /> {!isDriver && imageDispatch && ( <> @@ -224,28 +224,26 @@ export default function Home() { <Image src={imageDispatch} alt="Captured" - layout="fill" - objectFit="cover" + fill unoptimized className="p-2" + style={{ objectFit: "cover" }} /> </div> </> )} - <div> - <div className="h-4"></div> - <Button - className="w-[50%] sm:w-[25%]" - variant="contained" - color="error" - startIcon={<SaveAsOutlined />} - type="submit" - disabled={isLoading} - > - Simpan - </Button> - </div> + <div className="h-4" /> + <Button + className="w-[50%] sm:w-[25%]" + variant="contained" + color="error" + startIcon={<SaveAsOutlined />} + type="submit" + disabled={isLoading} + > + Simpan + </Button> </form> </div> )} |
