diff options
| author | Miqdad <ahmadmiqdad27@gmail.com> | 2025-09-30 16:20:05 +0700 |
|---|---|---|
| committer | Miqdad <ahmadmiqdad27@gmail.com> | 2025-09-30 16:20:05 +0700 |
| commit | 352000c186a2765416cd2fab6693e68bb62e9e53 (patch) | |
| tree | f979f04cb39a7afc3cad6f7ea5d0035cea31240f /app | |
| parent | 117be0f4b29ef8eb5622f7bf300fec570677cc23 (diff) | |
<Miqdad> done
Diffstat (limited to 'app')
| -rw-r--r-- | app/login/page.tsx | 2 | ||||
| -rw-r--r-- | app/page.tsx | 150 |
2 files changed, 133 insertions, 19 deletions
diff --git a/app/login/page.tsx b/app/login/page.tsx index 3ccefa4..c0d7ab8 100644 --- a/app/login/page.tsx +++ b/app/login/page.tsx @@ -154,7 +154,7 @@ const Login = () => { <div className="bg-[#fafeff] h-screen overflow-auto"> <Header /> <div className="py-4 px-4 sm:px-96 pt-20"> - <div className="bg-white py-6 px-4 sm:px-96 shadow-md rounded-sm"> + <div className="py-6 px-4 sm:px-96 shadow-md rounded-sm text-black"> <Typography component="h1" variant="h4" diff --git a/app/page.tsx b/app/page.tsx index 4841c09..add141f 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -6,7 +6,7 @@ import SjCamera from "./lib/camera/component/sjCamera"; import DispatchCamera from "./lib/camera/component/dispatchCamera"; import useCameraStore from "./lib/camera/hooks/useCameraStore"; import Header from "./lib/camera/component/hedear"; -import { Button } from "@mui/material"; +import { Button, FormControl, InputLabel, MenuItem, Select, FormHelperText } from "@mui/material"; import { SaveAsOutlined } from "@mui/icons-material"; import axios from "axios"; import odooApi from "./lib/api/odooApi"; @@ -16,11 +16,15 @@ import { getAuth } from "./lib/api/auth"; import { getCookie } from "cookies-next"; type Role = "driver" | "dispatch"; +type ShipMethod = "" | "self_pickup" | "indoteknik_delivery" | "ekspedisi"; export default function Home() { const [isLogin, setIsLogin] = useState<boolean>(true); const [isDriver, setIsDriver] = useState<boolean>(false); const [isDispatch, setIsDispatch] = useState<boolean>(false); + const [shippingMethod, setShippingMethod] = useState<ShipMethod>(""); + const [shipTouched, setShipTouched] = useState(false); + const { barcode, @@ -42,7 +46,6 @@ export default function Home() { router.push("/login"); return; } - // baca role dari cookie yang diset saat login const roleCookie = (getCookie("web_role") as string | undefined)?.toLowerCase() as Role | undefined; const role: Role | null = roleCookie === "driver" || roleCookie === "dispatch" ? roleCookie : null; @@ -61,16 +64,25 @@ export default function Home() { return; } - // Validasi sesuai role yang dipilih di login + // Dispatch: shipping method wajib + if (isDispatch) setShipTouched(true); + if (isDispatch && !shippingMethod) { + alert("Shipping Method wajib dipilih."); + setIsLoading(false); + return; + } + + + // Validasi foto sesuai role & shipping method if (isDispatch) { - // Dispatch: dispatch wajib, SJ opsional if (!imageDispatch) { alert("Foto Dispatch Wajib Diisi"); setIsLoading(false); return; } + // SJ opsional untuk self_pickup & ekspedisi → tidak divalidasi } else { - // Driver (atau non-dispatch): SJ & Penerima wajib + // Driver: SJ & Penerima wajib if (!imageSj || !imagePackage) { alert("Barcode, Foto SJ, dan Foto Penerima harus tersedia."); setIsLoading(false); @@ -79,7 +91,6 @@ export default function Home() { } try { - // siapkan base64 tanpa prefix, kalau kosong biarkan undefined const newSjImage = imageSj ? imageSj.replace(/^.*?,/, "") : undefined; const newPackageImage = imagePackage ? imagePackage.replace(/^.*?,/, "") : undefined; const newDispatchImage = @@ -87,15 +98,17 @@ export default function Home() { ? imageDispatch.replace(/^.*?,/, "") : imageDispatch || undefined; - // hanya kirim field yang ada + // Kirim hanya yang ada const submittedSj = !!newSjImage; const submittedPackage = !!newPackageImage; - const submittedDispatch = !!newDispatchImage && !isDriver; // dispatch hanya untuk non-driver + const submittedDispatch = !!newDispatchImage && !isDriver; const data: Record<string, string> = {}; if (submittedSj) data.sj_document = newSjImage!; if (submittedPackage) data.paket_document = newPackageImage!; if (submittedDispatch) data.dispatch_document = newDispatchImage!; + // (opsional) kirim shippingMethod jika backend mau simpan + if (isDispatch && shippingMethod) data.shipping_method = shippingMethod; const response = (await odooApi( "PUT", @@ -106,7 +119,7 @@ export default function Home() { if (response?.status?.code === 200) { alert("Berhasil Submit Data"); setBarcode(""); - + // Bersihkan HANYA yang dikirim if (submittedSj) setImageSj(""); if (submittedPackage) setImagePackage(""); if (submittedDispatch) setImageDispatch(""); @@ -128,6 +141,19 @@ export default function Home() { } }; + // dispatch: SJ hanya utk self_pickup & ekspedisi + const showSjForDispatch = + isDispatch && (shippingMethod === "self_pickup" || shippingMethod === "ekspedisi"); + + // dispatch: kamera dispatch tampil utk semua method (asal sudah dipilih) + const showDispatchForDispatch = isDispatch && shippingMethod !== ""; + + // preview SJ: sembunyikan kalau dispatch belum pilih method + const showSjPreview = !!imageSj && (!isDispatch || showSjForDispatch); + + // preview Dispatch: sembunyikan kalau dispatch belum pilih method + const showDispatchPreview = !!imageDispatch && (!isDispatch || showDispatchForDispatch); + return ( <div className="bg-white h-screen overflow-auto"> <Header /> @@ -138,27 +164,95 @@ export default function Home() { <BarcodeScanner /> </div> + {/* Shipping Method (khusus dispatch) */} + {isDispatch && ( + <div className="mt-4"> + <FormControl fullWidth size="small" required error={shipTouched && !shippingMethod}> + {/* shrink = kunci agar label tidak tumpuk dengan placeholder */} + <InputLabel id="shipping-label" shrink>Shipping Method</InputLabel> + <Select + labelId="shipping-label" + id="shipping" + label="Shipping Method" + value={shippingMethod} + displayEmpty + onChange={(e) => setShippingMethod(e.target.value as ShipMethod)} + onBlur={() => setShipTouched(true)} + renderValue={(selected) => { + if (!selected) return <span style={{ opacity: 0.6 }}>Pilih Shipping Method</span>; + const map: Record<string, string> = { + self_pickup: "Self Pickup", + indoteknik_delivery: "Indoteknik Delivery", + ekspedisi: "Ekspedisi", + }; + return map[selected as string] ?? ""; + }} + > + <MenuItem value=""> + <em>Pilih Shipping Method</em> + </MenuItem> + <MenuItem value="self_pickup">Self Pickup</MenuItem> + <MenuItem value="indoteknik_delivery">Indoteknik Delivery</MenuItem> + <MenuItem value="ekspedisi">Ekspedisi</MenuItem> + </Select> + {shipTouched && !shippingMethod && ( + <FormHelperText>Wajib pilih shipping method.</FormHelperText> + )} + </FormControl> + </div> + )} + + <div className="h-4" /> <div className="flex justify-between"> - {/* SJ: driver wajib, dispatch opsional → tampil untuk semua */} - <SjCamera /> - {/* Penerima: tidak diperlukan dispatch → sembunyikan saat dispatch */} - {!isDispatch && <PackageCamera />} - {/* Dispatch: wajib untuk dispatch; non-driver boleh tampil */} - {!isDriver && <DispatchCamera />} + {isDispatch ? ( + <> + {showSjForDispatch && <SjCamera />} + {showDispatchForDispatch && <DispatchCamera />} + {/* dispatch TIDAK perlu kamera penerima */} + </> + ) : ( + <> + {/* driver / non-dispatch */} + <SjCamera /> + <PackageCamera /> + {/* driver tidak menampilkan kamera dispatch */} + </> + )} </div> + <div className="h-2" /> - {imageSj && ( + {/* Preview SJ */} + {showSjPreview && ( <> <label className="block mt-2 text-sm font-medium text-gray-700 text-center"> Gambar Foto Surat Jalan </label> <div className="relative w-full h-[300px] border-2 border-gray-200 p-2 rounded-sm"> <Image - src={imageSj} + src={imageSj!} + alt="Captured" + fill + unoptimized + className="p-2" + style={{ objectFit: "cover" }} + /> + </div> + </> + )} + + {/* Preview Penerima (hanya non-dispatch) */} + {!isDispatch && imagePackage && ( + <> + <label className="block mt-2 text-sm font-medium text-gray-700 text-center"> + Gambar Foto Penerima + </label> + <div className="relative w-full h-[300px] border-2 border-gray-200 p-2 rounded-sm"> + <Image + src={imagePackage} alt="Captured" fill unoptimized @@ -169,9 +263,29 @@ export default function Home() { </> )} + {/* Preview Dispatch */} + {showDispatchPreview && ( + <> + <label className="block mt-2 text-sm font-medium text-gray-700 text-center"> + Gambar Foto Dispatch + </label> + <div className="relative w-full h-[300px] border-2 border-gray-200 p-2 rounded-sm"> + <Image + src={imageDispatch} + alt="Captured" + fill + unoptimized + className="p-2" + style={{ objectFit: "cover" }} + /> + </div> + </> + )} + + <div className="h-2" /> - {imagePackage && ( + {!isDispatch && imagePackage && ( <> <label className="block mt-2 text-sm font-medium text-gray-700 text-center"> Gambar Foto Penerima |
