summaryrefslogtreecommitdiff
path: root/app/page.tsx
diff options
context:
space:
mode:
authorMiqdad <ahmadmiqdad27@gmail.com>2025-11-06 15:27:18 +0700
committerMiqdad <ahmadmiqdad27@gmail.com>2025-11-06 15:27:18 +0700
commit77a0a082f0a5e1977c85a651a078376eab0d6df1 (patch)
treedc1fc01ab55aa2f56b18dcab012f3ae19cb714aa /app/page.tsx
parent8a0e4716aa12ce335758c84f7fdcb4b47cd9c2db (diff)
<MIqdad> multiple image SJ
Diffstat (limited to 'app/page.tsx')
-rw-r--r--app/page.tsx99
1 files changed, 66 insertions, 33 deletions
diff --git a/app/page.tsx b/app/page.tsx
index ae0e4d8..35609a6 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -13,8 +13,10 @@ import {
MenuItem,
Select,
FormHelperText,
+ IconButton,
+ Tooltip,
} from "@mui/material";
-import { SaveAsOutlined } from "@mui/icons-material";
+import { SaveAsOutlined, Close as CloseIcon } from "@mui/icons-material";
import axios from "axios";
import odooApi from "./lib/api/odooApi";
import { useEffect, useState } from "react";
@@ -27,7 +29,7 @@ type Role = "driver" | "dispatch";
type ShipMethod = "" | "self_pickup" | "indoteknik_delivery" | "ekspedisi";
export default function Home() {
- const [isLogin, setIsLogin] = useState<boolean>(false); // start false biar nggak nge-flash
+ const [isLogin, setIsLogin] = useState<boolean>(false);
const [isDriver, setIsDriver] = useState<boolean>(false);
const [isDispatch, setIsDispatch] = useState<boolean>(false);
const [shippingMethod, setShippingMethod] = useState<ShipMethod>("");
@@ -42,12 +44,13 @@ export default function Home() {
setImageSj,
setImagePackage,
setImageDispatch,
+ removeSjImage,
} = useCameraStore();
const [isLoading, setIsLoading] = useState<boolean>(false);
const router = useRouter();
- // Single effect: auth gate + set role
+ // Auth gate + role dari cookie
useEffect(() => {
const auth = getAuth();
if (!auth) {
@@ -73,7 +76,6 @@ export default function Home() {
return;
}
- // Dispatch: shipping method wajib
if (isDispatch) setShipTouched(true);
if (isDispatch && !shippingMethod) {
alert("Shipping Method wajib dipilih.");
@@ -81,17 +83,20 @@ export default function Home() {
return;
}
- // Validasi foto sesuai role & shipping method
+ const sjArr: string[] = Array.isArray(imageSj)
+ ? imageSj
+ : imageSj
+ ? [imageSj as unknown as string]
+ : [];
+
if (isDispatch) {
if (!imageDispatch) {
alert("Foto Dispatch Wajib Diisi");
setIsLoading(false);
return;
}
- // SJ opsional untuk self_pickup & ekspedisi
} else {
- // Driver: SJ & Penerima wajib
- if (!imageSj || !imagePackage) {
+ if (sjArr.length < 1 || !imagePackage) {
alert("Barcode, Foto SJ, dan Foto Penerima harus tersedia.");
setIsLoading(false);
return;
@@ -99,10 +104,13 @@ export default function Home() {
}
try {
- const newSjImage = imageSj ? imageSj.replace(/^.*?,/, "") : undefined;
+ const latestSj = sjArr.at(-1) || null;
+ const newSjImage = latestSj ? latestSj.replace(/^.*?,/, "") : undefined;
+
const newPackageImage = imagePackage
? imagePackage.replace(/^.*?,/, "")
: undefined;
+
const newDispatchImage =
imageDispatch && imageDispatch.startsWith("data:")
? imageDispatch.replace(/^.*?,/, "")
@@ -114,14 +122,11 @@ export default function Home() {
const submittedDispatch = !!newDispatchImage && !isDriver;
const data: Record<string, string> = {};
- if (submittedSj) data.sj_document = newSjImage!;
+ if (submittedSj) data.sj_documentations = newSjImage; // plural sesuai API
if (submittedPackage) data.paket_document = newPackageImage!;
if (submittedDispatch) data.dispatch_document = newDispatchImage!;
if (isDispatch && shippingMethod) data.shipping_method = shippingMethod;
-
- if (shippingMethod === "self_pickup") {
- data.self_pu = "true";
- }
+ if (shippingMethod === "self_pickup") data.self_pu = "true";
const response = (await odooApi(
"PUT",
@@ -132,8 +137,11 @@ export default function Home() {
if (response?.status?.code === 200) {
alert("Berhasil Submit Data");
setBarcode("");
- // Bersihkan HANYA yang dikirim
- if (submittedSj) setImageSj("");
+
+ if (submittedSj) {
+ const next = sjArr.slice(0, -1);
+ setImageSj(next);
+ }
if (submittedPackage) setImagePackage("");
if (submittedDispatch) setImageDispatch("");
} else if (response?.status?.code === 404) {
@@ -155,15 +163,19 @@ export default function Home() {
};
// === UI helpers ===
+ const sjArr: string[] = Array.isArray(imageSj)
+ ? imageSj
+ : imageSj
+ ? [imageSj as unknown as string]
+ : [];
+
// 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 showSjPreview = sjArr.length > 0 && (!isDispatch || showSjForDispatch);
const showDispatchPreview =
!!imageDispatch && (!isDispatch || showDispatchForDispatch);
@@ -234,7 +246,7 @@ export default function Home() {
<div className="h-4" />
- <div className="flex justify-between">
+ <div className="flex justify-between gap-3">
{isDispatch ? (
<>
{showSjForDispatch && <SjCamera />}
@@ -251,21 +263,42 @@ export default function Home() {
<div className="h-2" />
- {/* Preview SJ */}
+ {/* Preview SJ (multi) + Remove per item */}
{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!}
- alt="Captured"
- fill
- unoptimized
- className="p-2"
- style={{ objectFit: "cover" }}
- />
+ <div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
+ {sjArr.map((src, i) => (
+ <div
+ key={i}
+ className="relative w-full h-[180px] border-2 border-gray-200 rounded-sm"
+ >
+ <Image
+ src={src}
+ alt={`SJ ${i + 1}`}
+ fill
+ unoptimized
+ style={{ objectFit: "cover" }}
+ className="rounded-sm"
+ />
+ <div className="absolute top-1 right-1">
+ <Tooltip title="Remove">
+ <IconButton
+ size="small"
+ onClick={() => removeSjImage(i)}
+ sx={{
+ bgcolor: "rgba(255,255,255,0.85)",
+ "&:hover": { bgcolor: "rgba(255,255,255,1)" },
+ }}
+ >
+ <CloseIcon fontSize="small" />
+ </IconButton>
+ </Tooltip>
+ </div>
+ </div>
+ ))}
</div>
</>
)}
@@ -273,7 +306,7 @@ export default function Home() {
{/* Preview Penerima (hanya non-dispatch) */}
{!isDispatch && imagePackage && (
<>
- <label className="block mt-2 text-sm font-medium text-gray-700 text-center">
+ <label className="block mt-4 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">
@@ -292,7 +325,7 @@ export default function Home() {
{/* Preview Dispatch */}
{showDispatchPreview && (
<>
- <label className="block mt-2 text-sm font-medium text-gray-700 text-center">
+ <label className="block mt-4 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">