74 lines
2.9 KiB
TypeScript
74 lines
2.9 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Camera as CameraIcon, X } from 'lucide-react';
|
|
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
|
|
import { useNotification } from '@/hooks/useNotification';
|
|
|
|
interface PhotoTakerProps {
|
|
onPhotoTaken?: (webPath: string) => void;
|
|
onClose?: () => void;
|
|
}
|
|
|
|
export const PhotoTaker: React.FC<PhotoTakerProps> = ({ onPhotoTaken, onClose }) => {
|
|
const [photoUri, setPhotoUri] = useState<string | undefined>();
|
|
const notify = useNotification();
|
|
|
|
const takeAndSavePhoto = async () => {
|
|
try {
|
|
const image = await Camera.getPhoto({
|
|
quality: 90,
|
|
allowEditing: false, // Giữ nguyên ảnh gốc, không qua chỉnh sửa
|
|
resultType: CameraResultType.Uri,
|
|
source: CameraSource.Camera, // Mở camera trực tiếp
|
|
saveToGallery: true, // Tự động lưu ảnh gốc vào thư viện điện thoại
|
|
});
|
|
|
|
setPhotoUri(image.webPath);
|
|
notify({
|
|
title: 'Thành công',
|
|
message: 'Ảnh đã được chụp và tự động lưu vào thư viện điện thoại.',
|
|
type: 'success'
|
|
});
|
|
if (onPhotoTaken && image.webPath) {
|
|
onPhotoTaken(image.webPath);
|
|
}
|
|
} catch (error: any) {
|
|
console.error('Lỗi khi chụp hoặc lưu ảnh:', error);
|
|
if (error?.message !== 'User cancelled photos app') {
|
|
notify({
|
|
title: 'Lỗi chụp ảnh',
|
|
message: 'Không thể truy cập camera hoặc lưu ảnh.',
|
|
type: 'error'
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col items-center justify-center p-6 bg-slate-900/60 border border-slate-800/80 rounded-2xl w-full max-w-md mx-auto backdrop-blur-md">
|
|
<div className="flex justify-between items-center w-full mb-4">
|
|
<h3 className="text-sm font-black uppercase text-indigo-400 tracking-wider">Chụp ảnh hành trình</h3>
|
|
{onClose && (
|
|
<button onClick={onClose} className="p-1 hover:bg-slate-800 rounded-full transition-colors text-slate-400 hover:text-white">
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
)}
|
|
</div>
|
|
|
|
<button
|
|
onClick={takeAndSavePhoto}
|
|
className="w-full flex items-center justify-center gap-2 py-3 px-4 bg-indigo-650 hover:bg-indigo-700 active:scale-[0.98] text-white rounded-xl font-bold transition-all shadow-md cursor-pointer text-xs uppercase tracking-wider"
|
|
>
|
|
<CameraIcon className="w-4 h-4" />
|
|
Chụp và Lưu Ảnh Gốc
|
|
</button>
|
|
|
|
{photoUri && (
|
|
<div className="mt-6 w-full text-center border border-slate-800/85 bg-slate-950/40 p-4 rounded-xl">
|
|
<p className="text-[11px] text-slate-400 mb-2 font-semibold">Xem trước ảnh vừa chụp:</p>
|
|
<img src={photoUri} alt="Xem trước ảnh chụp" className="max-w-full h-auto rounded-lg mx-auto border border-slate-800" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|