fix: chọn camera hay thư viện
This commit is contained in:
BIN
Binary file not shown.
|
After Width: | Height: | Size: 844 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 408 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 844 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 408 KiB |
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { LogIn, Compass, Map as MapIcon, Camera, ShieldAlert } from 'lucide-react';
|
||||
import { LogIn, Compass, Map as MapIcon, Camera, ShieldAlert, Image as ImageIcon, X } from 'lucide-react';
|
||||
import { LoginModal } from '../components/LoginModal';
|
||||
import { ReportBusinessModal } from '../components/ReportBusinessModal';
|
||||
import { TagSelectModal } from '../components/TagSelectModal';
|
||||
@@ -21,7 +21,10 @@ export const LandingPage: React.FC<LandingPageProps> = ({ onGoToSignup, onGoToMa
|
||||
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false);
|
||||
const [isReportModalOpen, setIsReportModalOpen] = useState(false);
|
||||
const [isTagsModalOpen, setIsTagsModalOpen] = useState(false);
|
||||
const [isPhotoSourceModalOpen, setIsPhotoSourceModalOpen] = useState(false);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const cameraInputRef = useRef<HTMLInputElement>(null);
|
||||
const galleryInputRef = useRef<HTMLInputElement>(null);
|
||||
const [pendingPhotoFile, setPendingPhotoFile] = useState<File | null>(null);
|
||||
const [pendingPhotoLocation, setPendingPhotoLocation] = useState<GeolocationPosition | null>(null);
|
||||
const [photoPreviewUrl, setPhotoPreviewUrl] = useState<string>('');
|
||||
@@ -557,6 +560,25 @@ return (
|
||||
capture="environment"
|
||||
className="hidden"
|
||||
/>
|
||||
|
||||
{/* Camera input - capture="environment" for rear camera */}
|
||||
<input
|
||||
type="file"
|
||||
ref={cameraInputRef}
|
||||
onChange={handleFileChange}
|
||||
accept="image/*"
|
||||
capture="environment"
|
||||
className="hidden"
|
||||
/>
|
||||
|
||||
{/* Gallery input - no capture attribute for file picker */}
|
||||
<input
|
||||
type="file"
|
||||
ref={galleryInputRef}
|
||||
onChange={handleFileChange}
|
||||
accept="image/*"
|
||||
className="hidden"
|
||||
/>
|
||||
|
||||
{/* Unified Bottom Container: Gallery thumbnails on top, action buttons below */}
|
||||
<div className="absolute bottom-[calc(1.5rem+env(safe-area-inset-bottom,0px))] left-1/2 -translate-x-1/2 z-20 w-full px-4 flex flex-col items-center gap-4 max-w-md">
|
||||
@@ -607,7 +629,7 @@ return (
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
onClick={() => setIsPhotoSourceModalOpen(true)}
|
||||
className="flex-1 flex items-center justify-center gap-2 bg-white/20 backdrop-blur-lg hover:bg-white/30 text-white font-bold py-3.5 rounded-2xl transition-all shadow-2xl border border-white/30 active:scale-95 text-xs sm:text-sm whitespace-nowrap"
|
||||
>
|
||||
<Camera className="w-4.5 h-4.5" />
|
||||
@@ -655,6 +677,61 @@ return (
|
||||
onConfirm={handleConfirmTags}
|
||||
photoUrl={photoPreviewUrl}
|
||||
/>
|
||||
|
||||
{/* Photo Source Selection Modal */}
|
||||
{isPhotoSourceModalOpen && (
|
||||
<div className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4">
|
||||
<div className="bg-[var(--surface)] rounded-3xl shadow-2xl max-w-sm w-full overflow-hidden animate-in fade-in zoom-in-95 duration-200">
|
||||
{/* Header */}
|
||||
<div className="bg-gradient-to-r from-blue-600 to-blue-500 px-6 py-6 flex items-center justify-between">
|
||||
<h2 className="text-xl font-bold text-white">Chụp hoặc tải ảnh</h2>
|
||||
<button
|
||||
onClick={() => setIsPhotoSourceModalOpen(false)}
|
||||
className="p-1.5 hover:bg-white/20 rounded-full transition-colors"
|
||||
>
|
||||
<X className="w-5 h-5 text-white" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="p-6 space-y-3">
|
||||
{/* Camera Button */}
|
||||
<button
|
||||
onClick={() => {
|
||||
setIsPhotoSourceModalOpen(false);
|
||||
cameraInputRef.current?.click();
|
||||
}}
|
||||
className="w-full flex items-center gap-4 p-4 bg-[var(--background)] hover:bg-[var(--background-alt)] border border-[var(--border)] rounded-2xl transition-all active:scale-95"
|
||||
>
|
||||
<div className="flex-shrink-0 p-3 bg-blue-100 rounded-full">
|
||||
<Camera className="w-6 h-6 text-blue-600" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<div className="font-bold text-[var(--text-primary)]">Chụp ảnh bằng camera</div>
|
||||
<div className="text-sm text-[var(--text-muted)]">Dùng camera thiết bị của bạn</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{/* Gallery Button */}
|
||||
<button
|
||||
onClick={() => {
|
||||
setIsPhotoSourceModalOpen(false);
|
||||
galleryInputRef.current?.click();
|
||||
}}
|
||||
className="w-full flex items-center gap-4 p-4 bg-[var(--background)] hover:bg-[var(--background-alt)] border border-[var(--border)] rounded-2xl transition-all active:scale-95"
|
||||
>
|
||||
<div className="flex-shrink-0 p-3 bg-emerald-100 rounded-full">
|
||||
<ImageIcon className="w-6 h-6 text-emerald-600" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<div className="font-bold text-[var(--text-primary)]">Tải ảnh từ thư viện</div>
|
||||
<div className="text-sm text-[var(--text-muted)]">Chọn ảnh từ thiết bị của bạn</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user