summaryrefslogtreecommitdiff
path: root/app/lib
diff options
context:
space:
mode:
Diffstat (limited to 'app/lib')
-rw-r--r--app/lib/api/auth.ts42
-rw-r--r--app/lib/api/odooApi.ts56
-rw-r--r--app/lib/camera/component/camera.tsx79
-rw-r--r--app/lib/camera/component/cardFoto.tsx27
-rw-r--r--app/lib/camera/component/hedear.tsx21
-rw-r--r--app/lib/camera/component/pakageCamera.tsx44
-rw-r--r--app/lib/camera/component/scannerBarcode.tsx56
-rw-r--r--app/lib/camera/component/sjCamera.tsx48
-rw-r--r--app/lib/camera/hooks/useCamera.ts32
-rw-r--r--app/lib/camera/hooks/useCameraStore.ts22
10 files changed, 427 insertions, 0 deletions
diff --git a/app/lib/api/auth.ts b/app/lib/api/auth.ts
new file mode 100644
index 0000000..d954dc5
--- /dev/null
+++ b/app/lib/api/auth.ts
@@ -0,0 +1,42 @@
+import { deleteCookie, getCookie, setCookie } from "cookies-next"
+
+type AuthProps = {
+ id: number;
+ parentId: number;
+ parentName: string;
+ partnerId: number;
+ name: string;
+ email: string;
+ phone: string;
+ npwp: string;
+ mobile: string;
+ external: boolean;
+ company: boolean;
+ pricelist: string | null;
+ token: string;
+ feature : {
+ onlyReadyStock : boolean,
+ soApproval : boolean
+ }
+ };
+
+const getAuth = () : AuthProps | boolean => {
+ const auth = getCookie('auth')
+
+ if (auth) return JSON.parse(auth)
+ return false
+
+}
+
+const setAuth = (user : AuthProps) : boolean => {
+ setCookie('auth', JSON.stringify(user))
+ return true
+}
+
+
+const deleteAuth = () : boolean => {
+ deleteCookie('auth')
+ return true
+}
+
+export { getAuth , setAuth, deleteAuth} \ No newline at end of file
diff --git a/app/lib/api/odooApi.ts b/app/lib/api/odooApi.ts
new file mode 100644
index 0000000..c2c9d82
--- /dev/null
+++ b/app/lib/api/odooApi.ts
@@ -0,0 +1,56 @@
+import axios from "axios"
+import { getCookie, setCookie } from "cookies-next";
+import { getAuth } from "./auth";
+
+type axiosParameters = {
+ method : string,
+ url : string,
+ headers : {
+ Authorization : string,
+ 'Content-Type'? : string,
+ Token? : string
+ },
+ data ?: string
+}
+
+const renewToken = async () => {
+ const token = await axios.get(process.env.NEXT_PUBLIC_ODOO_API_HOST + '/api/token')
+ setCookie('token', token.data.result)
+ return token.data.result
+};
+
+const getToken = async () => {
+ let token = getCookie('token')
+ if (token == undefined) token = await renewToken()
+ 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));
+ }
+}
+
+
+export default odooApi \ No newline at end of file
diff --git a/app/lib/camera/component/camera.tsx b/app/lib/camera/component/camera.tsx
new file mode 100644
index 0000000..b398616
--- /dev/null
+++ b/app/lib/camera/component/camera.tsx
@@ -0,0 +1,79 @@
+import { CameraSharp } from "@mui/icons-material";
+import { Button, IconButton } from "@mui/material";
+import Image from "next/image";
+import React, { useRef } from "react";
+import Webcam from "react-webcam";
+
+interface WebcamCaptureProps {
+ image: string | null;
+ setImage: (image: string | null) => void;
+ isWebcamVisible: boolean;
+ setIsWebcamVisible: (isVisible: boolean) => void;
+}
+
+const WebcamCapture: React.FC<WebcamCaptureProps> = ({
+ image,
+ setImage,
+ isWebcamVisible,
+ setIsWebcamVisible,
+}) => {
+ const webcamRef = useRef<Webcam>(null);
+
+ // Mengambil foto dari webcam
+ const capture = () => {
+ const image = webcamRef.current?.getScreenshot();
+ setIsWebcamVisible(false);
+ setImage(image || null);
+ };
+
+ const takePicture = () => {
+ setImage(null);
+ setIsWebcamVisible(true);
+ };
+
+ // Mengatur ukuran webcam
+ const videoConstraints = {
+ width: 500,
+ height: 480,
+ facingMode: {
+ exact: "environment" // untuk kamera belakang
+ },
+ };
+
+ return (
+ <div className="items-center">
+ {!isWebcamVisible && (
+ <Button variant="text" size="large" onClick={() => takePicture()}>
+ Ambil Foto Surat Jalan
+ </Button>
+ )}
+
+ {isWebcamVisible && (
+ <div>
+ <Webcam
+ audio={false}
+ ref={webcamRef}
+ screenshotFormat="image/jpeg"
+ videoConstraints={videoConstraints}
+ />
+ <IconButton aria-label="camera" size="large" onClick={() => capture()}>
+ <CameraSharp fontSize="inherit" />
+ </IconButton>
+ </div>
+ )}
+ {image && (
+ <div>
+ <Image
+ src={image}
+ alt="Captured"
+ width={500}
+ height={480}
+ unoptimized
+ />
+ </div>
+ )}
+ </div>
+ );
+};
+
+export default WebcamCapture;
diff --git a/app/lib/camera/component/cardFoto.tsx b/app/lib/camera/component/cardFoto.tsx
new file mode 100644
index 0000000..34da216
--- /dev/null
+++ b/app/lib/camera/component/cardFoto.tsx
@@ -0,0 +1,27 @@
+import { Card, CardContent, Typography } from "@mui/material";
+import Image from "next/image";
+import React from "react";
+import useCameraStore from "../hooks/useCameraStore";
+
+const CardFotos = () => {
+ const { imagePackage } = useCameraStore();
+ return (
+ <Card sx={{ maxWidth: 200 }}>
+ <Image
+ src={imagePackage ?? ''}
+ alt="Captured"
+ layout="fill"
+ objectFit="cover"
+ unoptimized
+ className="p-2"
+ />
+ <CardContent>
+ <Typography gutterBottom variant="h5" component="div">
+ Lizard
+ </Typography>
+ </CardContent>
+ </Card>
+ );
+}
+
+export default CardFotos
diff --git a/app/lib/camera/component/hedear.tsx b/app/lib/camera/component/hedear.tsx
new file mode 100644
index 0000000..5cf3f1d
--- /dev/null
+++ b/app/lib/camera/component/hedear.tsx
@@ -0,0 +1,21 @@
+// components/Header.tsx
+import Image from "next/image";
+
+export default function Header() {
+ 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
+ alt="Logo"
+ width={120}
+ height={60}
+ className="rounded-full"
+ />
+ </div>
+
+ </div>
+ </nav>
+ );
+}
diff --git a/app/lib/camera/component/pakageCamera.tsx b/app/lib/camera/component/pakageCamera.tsx
new file mode 100644
index 0000000..e0c7158
--- /dev/null
+++ b/app/lib/camera/component/pakageCamera.tsx
@@ -0,0 +1,44 @@
+import React from "react";
+import useCameraStore from "../hooks/useCameraStore";
+import { IconButton } from "@mui/material";
+import { PhotoCameraFrontOutlined } from "@mui/icons-material";
+
+const PackageCamera: React.FC = () => {
+ const { setImagePackage } = useCameraStore();
+ const handleCapture = (event: React.ChangeEvent<HTMLInputElement>) => {
+ const file = event.target.files?.[0];
+ if (file) {
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ setImagePackage(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/*"
+ capture="environment"
+ onChange={handleCapture}
+ className="hidden"
+ id="pakageCameraInput"
+ />
+ <label htmlFor="pakageCameraInput" className="text-gray-600">
+ <IconButton
+ color="primary"
+ aria-label="upload picture"
+ component="span"
+ >
+ <PhotoCameraFrontOutlined fontSize="large" />
+ </IconButton>
+ <br />
+ Foto Penerima
+ </label>
+ </div>
+ );
+};
+
+export default PackageCamera;
diff --git a/app/lib/camera/component/scannerBarcode.tsx b/app/lib/camera/component/scannerBarcode.tsx
new file mode 100644
index 0000000..3079e33
--- /dev/null
+++ b/app/lib/camera/component/scannerBarcode.tsx
@@ -0,0 +1,56 @@
+import { QrCode2 } from "@mui/icons-material";
+import { Button, TextField } from "@mui/material";
+import dynamic from "next/dynamic";
+import React, { useState } from "react";
+import useCameraStore from "../hooks/useCameraStore";
+
+const BarcodeScannerComponent = dynamic(
+ () => import("react-qr-barcode-scanner"),
+ { ssr: false }
+);
+const BarcodeScanner: React.FC = () => {
+ const { barcode, setBarcode } = useCameraStore();
+ const [isCameraActive, setIsCameraActive] = useState(false);
+
+ return (
+ <div>
+ <Button
+ variant="outlined"
+ onClick={() => setIsCameraActive(!isCameraActive)}
+ startIcon={<QrCode2 />}
+ color="error"
+ className="mb-2"
+ >
+ {isCameraActive ? "Cancel" : "Scane Code"}
+ </Button>
+
+ {isCameraActive && (
+ <BarcodeScannerComponent
+ width={500} // Tingkatkan ukuran untuk memperjelas gambar
+ height={300}
+ onUpdate={(err, result) => {
+ if (result) {
+ setBarcode(result.getText());
+ setIsCameraActive(false);
+ }
+ }}
+ />
+ )}
+
+ <div className="mt-4">
+ <TextField
+ fullWidth
+ label="Detected Picking Code"
+ id="outlined-basic"
+ value={barcode}
+ onChange={ (e) => setBarcode(e.target.value) }
+ InputLabelProps={{
+ shrink: true, // Label akan selalu berada di atas (outline)
+ }}
+ />
+ </div>
+ </div>
+ );
+};
+
+export default BarcodeScanner;
diff --git a/app/lib/camera/component/sjCamera.tsx b/app/lib/camera/component/sjCamera.tsx
new file mode 100644
index 0000000..5cc39ad
--- /dev/null
+++ b/app/lib/camera/component/sjCamera.tsx
@@ -0,0 +1,48 @@
+import React from "react";
+import useCameraStore from "../hooks/useCameraStore";
+import { IconButton } from "@mui/material";
+import { PendingActions } from "@mui/icons-material";
+
+const SjCamera: React.FC = () => {
+ const { setImageSj } = useCameraStore();
+ const handleSuratJalanCapture = (
+ event: React.ChangeEvent<HTMLInputElement>
+ ) => {
+ const file = event.target.files?.[0];
+ if (file) {
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ setImageSj(reader.result as string);
+ };
+ reader.readAsDataURL(file);
+ }
+ };
+
+ return (
+ <>
+ <div className="p-4 py-8 items-center border-2 rounded-md shadow-sm w-[49%] text-center">
+ <input
+ type="file"
+ accept="image/*"
+ capture="environment"
+ onChange={handleSuratJalanCapture}
+ className="hidden"
+ id="suratJalanInput"
+ />
+ <label htmlFor="suratJalanInput" className="text-gray-600">
+ <IconButton
+ color="primary"
+ aria-label="upload picture"
+ component="span"
+ >
+ <PendingActions fontSize="large" />
+ </IconButton>
+ <br />
+ Foto Surat Jalan
+ </label>
+ </div>
+ </>
+ );
+};
+
+export default SjCamera;
diff --git a/app/lib/camera/hooks/useCamera.ts b/app/lib/camera/hooks/useCamera.ts
new file mode 100644
index 0000000..d85d978
--- /dev/null
+++ b/app/lib/camera/hooks/useCamera.ts
@@ -0,0 +1,32 @@
+import { useState } from "react"
+
+const useCamera = () => {
+
+ const [imageSJ, setImageSj] = useState<string | null>(null)
+ const [imagePackage, setImagePackage] = useState<string | null>(null)
+ const [barcode, setBarcode] = useState<string | null>(null)
+
+ const [isWebcamVisibleSj, setIsWebcamVisibleSJ] = useState<boolean>(false)
+ const [isWebcamVisiblePackage, setIsWebcamVisiblePackage] = useState<boolean>(false)
+
+ const handleSubmit = () => {
+ setIsWebcamVisibleSJ(false)
+ }
+
+
+ return {
+ barcode,
+ setBarcode,
+ imageSJ,
+ imagePackage,
+ setImageSj,
+ setImagePackage,
+ isWebcamVisibleSj,
+ isWebcamVisiblePackage,
+ setIsWebcamVisibleSJ,
+ setIsWebcamVisiblePackage,
+ handleSubmit
+ }
+}
+
+export default useCamera \ No newline at end of file
diff --git a/app/lib/camera/hooks/useCameraStore.ts b/app/lib/camera/hooks/useCameraStore.ts
new file mode 100644
index 0000000..c922d1c
--- /dev/null
+++ b/app/lib/camera/hooks/useCameraStore.ts
@@ -0,0 +1,22 @@
+// store/useCameraStore.ts
+import { create } from 'zustand'
+
+interface CameraStore {
+ barcode: string | null
+ setBarcode: (barcode: string) => void
+ imageSj: string | null
+ setImageSj: (image: string) => void
+ imagePackage: string | null
+ setImagePackage: (image: string) => void
+}
+
+const useCameraStore = create<CameraStore>((set) => ({
+ barcode: null,
+ setBarcode: (barcode: string) => set({ barcode: barcode }),
+ imageSj: null,
+ setImageSj: (image: string) => set({ imageSj: image }),
+ imagePackage: null,
+ setImagePackage: (image: string) => set({ imagePackage: image }),
+}))
+
+export default useCameraStore \ No newline at end of file