summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/lib/api/odooApi.ts61
-rw-r--r--app/lib/camera/component/dispatchCamera.tsx43
-rw-r--r--app/lib/camera/component/hedear.tsx37
-rw-r--r--app/lib/camera/hooks/useCameraStore.ts4
-rw-r--r--app/page.tsx31
5 files changed, 138 insertions, 38 deletions
diff --git a/app/lib/api/odooApi.ts b/app/lib/api/odooApi.ts
index c2c9d82..fab3e0c 100644
--- a/app/lib/api/odooApi.ts
+++ b/app/lib/api/odooApi.ts
@@ -25,32 +25,43 @@ const getToken = async () => {
return token
};
-const odooApi = async (method : string, url : string, data = {}, headers = {}) => {
- try {
- const token = await getToken()
- const auth = getAuth();
- const axiosParameter : axiosParameters = {
- method,
- url: process.env.NEXT_PUBLIC_ODOO_API_HOST + url,
- headers: { Authorization: token ? token : '', ...headers },
- };
- console.log('ini adalah tipe',axiosParameter)
- if (auth && typeof auth === 'object' && 'token' in auth) {
- axiosParameter.headers['Token'] = auth.token;
- }
- if (method.toUpperCase() == 'POST')
- axiosParameter.headers['Content-Type'] =
- 'application/x-www-form-urlencoded';
- if (Object.keys(data).length > 0)
- axiosParameter.data = new URLSearchParams(
- Object.entries(data)
- ).toString();
- const response = await axios(axiosParameter);
- return response.data;
- } catch (error) {
- console.log( JSON.stringify(error));
+const odooApi = async (method: string, url: string, data = {}, headers = {}) => {
+ try {
+ const token = await getToken();
+ const auth = getAuth();
+
+ const axiosParameter: axiosParameters = {
+ method,
+ url: process.env.NEXT_PUBLIC_ODOO_API_HOST + url,
+ headers: { Authorization: token ? token : '', ...headers },
+ };
+
+ if (auth && typeof auth === 'object' && 'token' in auth) {
+ axiosParameter.headers['Token'] = (auth as any).token;
}
-}
+
+ const upper = method.toUpperCase();
+
+ // Set Content-Type untuk method yang kirim body
+ if (upper === 'POST' || upper === 'PUT' || upper === 'PATCH') {
+ axiosParameter.headers['Content-Type'] = 'application/x-www-form-urlencoded';
+ }
+
+ // Hanya kirim body untuk method yang memang pakai body
+ if (Object.keys(data).length > 0 && upper !== 'GET' && upper !== 'HEAD') {
+ const entries = Object.entries(data).filter(
+ ([, v]) => v !== undefined && v !== null && v !== ''
+ ) as [string, string][];
+ axiosParameter.data = new URLSearchParams(entries).toString();
+ }
+
+ const response = await axios(axiosParameter);
+ return response.data;
+ } catch (error) {
+ console.log(JSON.stringify(error));
+ }
+};
+
export default odooApi \ No newline at end of file
diff --git a/app/lib/camera/component/dispatchCamera.tsx b/app/lib/camera/component/dispatchCamera.tsx
new file mode 100644
index 0000000..2591413
--- /dev/null
+++ b/app/lib/camera/component/dispatchCamera.tsx
@@ -0,0 +1,43 @@
+import React from "react";
+import useCameraStore from "../hooks/useCameraStore";
+import { IconButton } from "@mui/material";
+import { LocalShipping } from "@mui/icons-material";
+
+const DispatchCamera: React.FC = () => {
+ const { setImageDispatch } = useCameraStore();
+ const handleCapture = (event: React.ChangeEvent<HTMLInputElement>) => {
+ const file = event.target.files?.[0];
+ if (file) {
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ setImageDispatch(reader.result as string);
+ };
+ reader.readAsDataURL(file);
+ }
+ };
+
+ return (
+ <div className="px-4 py-8 items-center border-2 rounded-md shadow-sm w-[49%] text-center ">
+ <input
+ type="file"
+ accept="image/*"
+ onChange={handleCapture}
+ className="hidden"
+ id="dispatchCameraInput"
+ />
+ <label htmlFor="dispatchCameraInput" className="text-gray-600">
+ <IconButton
+ color="primary"
+ aria-label="upload picture"
+ component="span"
+ >
+ <LocalShipping fontSize="large" />
+ </IconButton>
+ <br />
+ Foto Dispatch
+ </label>
+ </div>
+ );
+};
+
+export default DispatchCamera;
diff --git a/app/lib/camera/component/hedear.tsx b/app/lib/camera/component/hedear.tsx
index 2a8bfc6..81f5d01 100644
--- a/app/lib/camera/component/hedear.tsx
+++ b/app/lib/camera/component/hedear.tsx
@@ -1,36 +1,53 @@
// components/Header.tsx
+"use client";
+
import Image from "next/image";
import { deleteAuth, getAuth } from "../../api/auth";
import { Button } from "@mui/material";
import { useRouter } from "next/navigation";
+import { useEffect, useState } from "react";
export default function Header() {
- const auth = getAuth();
- const route = useRouter();
+ const router = useRouter();
+ const [mounted, setMounted] = useState(false);
+ const [auth, setAuth] = useState<any>(null);
+
+ useEffect(() => {
+ setMounted(true);
+ try {
+ setAuth(getAuth());
+ } catch {
+ setAuth(null);
+ }
+ }, []);
- const handleSigOut = () => {
+ const handleSignOut = () => {
deleteAuth();
- route.push('/login');
+ router.push("/login");
};
+
return (
<nav className="fixed top-0 left-0 w-full bg-white border-b-2 border-red-500 py-4 px-4 sm:px-96 z-50 shadow-md">
<div className="flex justify-between items-center">
<div className="flex items-center">
<Image
- src="/images/indoteknik-logo.png" // Ganti dengan path logo Anda
+ src="/images/indoteknik-logo.png"
alt="Logo"
width={120}
height={60}
className="rounded-full"
+ priority
/>
</div>
- {auth && (
- <div>
- <Button size="small" onClick={() => handleSigOut()}>
+ <div>
+ {mounted && auth ? (
+ <Button size="small" onClick={handleSignOut}>
Logout
</Button>
- </div>
- )}
+ ) : (
+ <span className="inline-block h-8 w-16" aria-hidden />
+ )}
+ </div>
</div>
</nav>
);
diff --git a/app/lib/camera/hooks/useCameraStore.ts b/app/lib/camera/hooks/useCameraStore.ts
index c922d1c..359bcb3 100644
--- a/app/lib/camera/hooks/useCameraStore.ts
+++ b/app/lib/camera/hooks/useCameraStore.ts
@@ -8,6 +8,8 @@ interface CameraStore {
setImageSj: (image: string) => void
imagePackage: string | null
setImagePackage: (image: string) => void
+ imageDispatch: string | null
+ setImageDispatch: (image: string) => void
}
const useCameraStore = create<CameraStore>((set) => ({
@@ -17,6 +19,8 @@ const useCameraStore = create<CameraStore>((set) => ({
setImageSj: (image: string) => set({ imageSj: image }),
imagePackage: null,
setImagePackage: (image: string) => set({ imagePackage: image }),
+ imageDispatch: null,
+ setImageDispatch: (image: string) => set({ imageDispatch: image }),
}))
export default useCameraStore \ No newline at end of file
diff --git a/app/page.tsx b/app/page.tsx
index f12f746..363b6b6 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -3,6 +3,7 @@ import Image from "next/image";
import PackageCamera from "./lib/camera/component/pakageCamera";
import BarcodeScanner from "./lib/camera/component/scannerBarcode";
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";
@@ -19,9 +20,11 @@ export default function Home() {
barcode,
imageSj,
imagePackage,
+ imageDispatch,
setBarcode,
setImageSj,
setImagePackage,
+ setImageDispatch,
} = useCameraStore();
const [isLoading, setIsLoading] = useState<boolean>(false);
@@ -41,7 +44,7 @@ export default function Home() {
event.preventDefault();
setIsLoading(true);
- if (!barcode || !imageSj || !imagePackage) {
+ if (!barcode || !imageSj || !imagePackage || !imageDispatch) {
alert("Barcode dan gambar harus tersedia.");
setIsLoading(false);
return;
@@ -50,10 +53,12 @@ export default function Home() {
try {
const newSjImage = imageSj.replace(/^.*?,/, "");
const newPackageImage = imagePackage.replace(/^.*?,/, "");
+ const newDispatchImage = imageDispatch.replace(/^.*?,/, "");
const data = {
- sj_document: newSjImage, // Kirim base64 lengkap dengan prefix
- paket_document: newPackageImage, // Kirim base64 lengkap dengan prefix
+ sj_document: newSjImage,
+ paket_document: newPackageImage,
+ dispatch_document: newDispatchImage,
};
const response = await odooApi(
@@ -66,6 +71,7 @@ export default function Home() {
setBarcode("");
setImageSj("");
setImagePackage("");
+ setImageDispatch("");
setIsLoading(false);
}else if(response.status.code == 404){
alert("Gagal Submit Data, Picking Code Tidak Ditemukan " );
@@ -101,6 +107,7 @@ export default function Home() {
<div className="flex justify-between">
<SjCamera />
<PackageCamera />
+ <DispatchCamera />
</div>
<div className="h-2"></div>
@@ -141,6 +148,24 @@ export default function Home() {
</div>
</>
)}
+ <div className="h-2"></div>
+ {imageDispatch && (
+ <>
+ <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"
+ layout="fill"
+ objectFit="cover"
+ unoptimized
+ className="p-2"
+ />
+ </div>
+ </>
+ )}
<div>
<div className="h-4"></div>
<Button