diff options
| author | Miqdad <ahmadmiqdad27@gmail.com> | 2025-11-06 15:27:18 +0700 |
|---|---|---|
| committer | Miqdad <ahmadmiqdad27@gmail.com> | 2025-11-06 15:27:18 +0700 |
| commit | 77a0a082f0a5e1977c85a651a078376eab0d6df1 (patch) | |
| tree | dc1fc01ab55aa2f56b18dcab012f3ae19cb714aa /app/lib | |
| parent | 8a0e4716aa12ce335758c84f7fdcb4b47cd9c2db (diff) | |
<MIqdad> multiple image SJ
Diffstat (limited to 'app/lib')
| -rw-r--r-- | app/lib/camera/component/sjCamera.tsx | 89 | ||||
| -rw-r--r-- | app/lib/camera/hooks/useCameraStore.ts | 54 |
2 files changed, 91 insertions, 52 deletions
diff --git a/app/lib/camera/component/sjCamera.tsx b/app/lib/camera/component/sjCamera.tsx index 9dbe2dc..ea5c5e2 100644 --- a/app/lib/camera/component/sjCamera.tsx +++ b/app/lib/camera/component/sjCamera.tsx @@ -1,46 +1,73 @@ -import React from "react"; +import React, { useRef } 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 = ( + const fileRef = useRef<HTMLInputElement | null>(null); + + const readFilesAsDataURL = (files: FileList | null): Promise<string[]> => + new Promise((resolve) => { + if (!files || files.length === 0) return resolve([]); + const list = Array.from(files); + const out: string[] = []; + let done = 0; + list.forEach((f) => { + const fr = new FileReader(); + fr.onload = (e) => { + const dataUrl = (e.target?.result as string) || ""; + if (dataUrl) out.push(dataUrl); + done += 1; + if (done === list.length) resolve(out); + }; + fr.onerror = () => { + done += 1; + if (done === list.length) resolve(out); + }; + fr.readAsDataURL(f); + }); + }); + + const handleSuratJalanCapture = async ( 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); + const imgs = await readFilesAsDataURL(event.target.files); + if (imgs.length > 0) { + // APPEND: panggil setImageSj untuk tiap foto + imgs.forEach((img) => setImageSj(img)); } + // reset supaya bisa pilih file yang sama lagi + if (fileRef.current) fileRef.current.value = ""; }; return ( - <> - <div className="p-4 py-8 items-center border-2 rounded-md shadow-sm w-[49%] text-center"> - <input - type="file" - accept="image/*" - 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> - </> + <div className="p-4 py-8 items-center border-2 rounded-md shadow-sm w-[49%] text-center"> + <input + ref={fileRef} + id="suratJalanInput" + type="file" + accept="image/*" + capture="environment" + multiple + className="hidden" + onChange={handleSuratJalanCapture} + /> + <label + htmlFor="suratJalanInput" + className="text-gray-600 cursor-pointer select-none" + > + <IconButton + color="primary" + aria-label="upload picture" + component="span" + > + <PendingActions fontSize="large" /> + </IconButton> + <br /> + Foto Surat Jalan + </label> + </div> ); }; diff --git a/app/lib/camera/hooks/useCameraStore.ts b/app/lib/camera/hooks/useCameraStore.ts index ad83074..874c627 100644 --- a/app/lib/camera/hooks/useCameraStore.ts +++ b/app/lib/camera/hooks/useCameraStore.ts @@ -1,26 +1,38 @@ -// store/useCameraStore.ts -import { create } from 'zustand' +// lib/camera/hooks/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 - imageDispatch: string | null - setImageDispatch: (image: string) => void + barcode: string; + setBarcode: (barcode: string) => void; + + imageSj: string[]; // dataURL + setImageSj: (imgOrArr: string | string[]) => void; + removeSjImage: (idx: number) => void; + + imagePackage: string | null; + setImagePackage: (image: string | null) => void; + + imageDispatch: string | null; + setImageDispatch: (image: string | null) => void; } const useCameraStore = create<CameraStore>((set) => ({ - barcode: '', - setBarcode: (barcode: string) => set({ barcode: barcode }), - imageSj: '', - setImageSj: (image: string) => set({ imageSj: image }), - imagePackage: '', - setImagePackage: (image: string) => set({ imagePackage: image }), - imageDispatch: '', - setImageDispatch: (image: string) => set({ imageDispatch: image }), -})) - -export default useCameraStore
\ No newline at end of file + barcode: "", + setBarcode: (barcode) => set({ barcode }), + + imageSj: [], + setImageSj: (imgOrArr) => + set((s) => ({ + imageSj: Array.isArray(imgOrArr) ? imgOrArr : [...s.imageSj, imgOrArr], + })), + removeSjImage: (idx) => + set((s) => ({ imageSj: s.imageSj.filter((_, i) => i !== idx) })), + + imagePackage: "", + setImagePackage: (image) => set({ imagePackage: image }), + + imageDispatch: "", + setImageDispatch: (image) => set({ imageDispatch: image }), +})); + +export default useCameraStore; |
