feat: enhance 'Almoxarifado' UI with improved styling, updated component layouts, and added barcode functionality for better inventory management and user experience

This commit is contained in:
2025-12-22 00:08:13 -03:00
parent ef9dbedb34
commit ae4f8fc6b3
10 changed files with 1283 additions and 753 deletions

View File

@@ -71,11 +71,7 @@
reader.readAsDataURL(file);
}
function resizeImage(
dataUrl: string,
maxWidth: number,
maxHeight: number
): Promise<string> {
function resizeImage(dataUrl: string, maxWidth: number, maxHeight: number): Promise<string> {
return new Promise((resolve, reject) => {
const img = new window.Image();
img.onload = () => {
@@ -171,10 +167,10 @@
// Atribuir stream ao vídeo
videoElement.srcObject = stream;
// Aguardar o vídeo estar pronto e começar a reproduzir
await videoElement.play();
// Aguardar metadata estar carregado
if (videoElement.readyState < 2) {
await new Promise<void>((resolve, reject) => {
@@ -204,10 +200,11 @@
} catch (err) {
console.error('Erro ao acessar câmera:', err);
let errorMessage = 'Erro ao acessar câmera';
if (err instanceof Error) {
if (err.name === 'NotAllowedError' || err.name === 'PermissionDeniedError') {
errorMessage = 'Permissão de acesso à câmera negada. Por favor, permita o acesso à câmera nas configurações do navegador.';
errorMessage =
'Permissão de acesso à câmera negada. Por favor, permita o acesso à câmera nas configurações do navegador.';
} else if (err.name === 'NotFoundError' || err.name === 'DevicesNotFoundError') {
errorMessage = 'Nenhuma câmera encontrada no dispositivo.';
} else if (err.name === 'NotReadableError' || err.name === 'TrackStartError') {
@@ -216,7 +213,7 @@
errorMessage = err.message || errorMessage;
}
}
error = errorMessage;
showCamera = false;
capturing = false;
@@ -280,11 +277,14 @@
// Sincronizar preview com value sempre que value mudar
$effect(() => {
// Acessar value para criar dependência reativa
const currentValue = value;
// Sempre sincronizar quando value mudar
preview = value;
if (currentValue !== preview) {
preview = currentValue;
}
});
// Limpar stream quando o componente for desmontado
$effect(() => {
return () => {
@@ -305,7 +305,11 @@
{#if preview}
<div class="relative inline-block">
<img src={preview} alt="Preview da imagem do produto" class="max-w-full max-h-64 rounded-lg" />
<img
src={preview}
alt="Preview da imagem do produto"
class="max-h-64 max-w-full rounded-lg"
/>
<button
type="button"
class="btn btn-sm btn-circle btn-error absolute top-2 right-2"
@@ -318,7 +322,7 @@
{:else}
<div class="flex flex-col gap-4">
<div
class="border-2 border-dashed border-base-300 rounded-lg p-8 text-center cursor-pointer hover:border-primary transition-colors"
class="border-base-300 hover:border-primary cursor-pointer rounded-lg border-2 border-dashed p-8 text-center transition-colors"
onclick={triggerFileInput}
role="button"
tabindex="0"
@@ -329,18 +333,14 @@
}
}}
>
<Upload class="h-12 w-12 mx-auto mb-4 text-base-content/40" />
<p class="text-base-content/70 font-medium mb-2">Clique para fazer upload da imagem</p>
<p class="text-sm text-base-content/50">
<Upload class="text-base-content/40 mx-auto mb-4 h-12 w-12" />
<p class="text-base-content/70 mb-2 font-medium">Clique para fazer upload da imagem</p>
<p class="text-base-content/50 text-sm">
PNG, JPG ou GIF até {maxSizeMB}MB
</p>
</div>
<div class="divider text-sm">ou</div>
<button
type="button"
class="btn btn-outline btn-primary w-full"
onclick={openCamera}
>
<button type="button" class="btn btn-outline btn-primary w-full" onclick={openCamera}>
<Camera class="h-5 w-5" />
Capturar da Câmera
</button>
@@ -354,7 +354,7 @@
{/if}
{#if preview}
<div class="flex gap-2 mt-4">
<div class="mt-4 flex gap-2">
<button
type="button"
class="btn btn-sm btn-outline btn-primary flex-1"
@@ -363,11 +363,7 @@
<ImageIcon class="h-4 w-4" />
Alterar Imagem
</button>
<button
type="button"
class="btn btn-sm btn-outline btn-primary flex-1"
onclick={openCamera}
>
<button type="button" class="btn btn-sm btn-outline btn-primary flex-1" onclick={openCamera}>
<Camera class="h-4 w-4" />
Capturar Foto
</button>
@@ -377,12 +373,15 @@
<!-- Modal da Câmera -->
{#if showCamera}
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/80" onclick={closeCamera}>
<div
class="fixed inset-0 z-50 flex items-center justify-center bg-black/80"
onclick={closeCamera}
>
<div
class="bg-base-100 rounded-lg shadow-2xl p-6 max-w-2xl w-full mx-4"
class="bg-base-100 mx-4 w-full max-w-2xl rounded-lg p-6 shadow-2xl"
onclick={(e) => e.stopPropagation()}
>
<div class="flex items-center justify-between mb-4">
<div class="mb-4 flex items-center justify-between">
<h3 class="text-xl font-bold">Capturar Foto</h3>
<button
type="button"
@@ -394,19 +393,24 @@
</button>
</div>
<div class="relative bg-black rounded-lg overflow-hidden mb-4" style="aspect-ratio: 4/3; min-height: 300px;">
<div
class="relative mb-4 overflow-hidden rounded-lg bg-black"
style="aspect-ratio: 4/3; min-height: 300px;"
>
{#if showCamera}
<video
bind:this={videoElement}
autoplay
playsinline
muted
class="w-full h-full object-cover"
style="transform: scaleX(-1); opacity: {capturing ? '1' : '0'}; transition: opacity 0.3s;"
class="h-full w-full object-cover"
style="transform: scaleX(-1); opacity: {capturing
? '1'
: '0'}; transition: opacity 0.3s;"
></video>
{/if}
{#if !capturing}
<div class="flex items-center justify-center h-full absolute inset-0 z-10">
<div class="absolute inset-0 z-10 flex h-full items-center justify-center">
<div class="text-center">
<span class="loading loading-spinner loading-lg text-primary mb-2"></span>
<p class="text-base-content/70 text-sm">Iniciando câmera...</p>
@@ -415,20 +419,9 @@
{/if}
</div>
<div class="flex gap-2 justify-end">
<button
type="button"
class="btn btn-ghost"
onclick={closeCamera}
>
Cancelar
</button>
<button
type="button"
class="btn btn-primary"
onclick={capturePhoto}
disabled={!capturing}
>
<div class="flex justify-end gap-2">
<button type="button" class="btn btn-ghost" onclick={closeCamera}> Cancelar </button>
<button type="button" class="btn btn-primary" onclick={capturePhoto} disabled={!capturing}>
<Camera class="h-5 w-5" />
Capturar Foto
</button>
@@ -442,4 +435,3 @@
width: 100%;
}
</style>