Made changes to CSS and merged together.

This commit is contained in:
2025-12-17 23:16:20 -05:00
parent 2402645911
commit 5fd71f8c94
2 changed files with 23 additions and 127 deletions

View File

@@ -46,28 +46,6 @@ input[type='number'],
box-sizing: border-box;
}
.btn.cancel,
button[type='button'] {
background: #f3f3f3;
color: #666;
}
.btn.save,
button[type='submit'] {
background: #667eea;
color: #fff;
border: none;
border-radius: 8px;
padding: 0.6rem 1.4rem;
font-weight: 600;
font-size: 1rem;
cursor: pointer;
transition: background 0.18s;
}
.btn.save:hover,
button[type='submit']:hover:not(:disabled) {
background: #5a67d8;
}
.loading-message {
text-align: center;
color: #666;

View File

@@ -41,18 +41,7 @@ const onFileChange = async (event: Event) => {
if (localImageUrl.value) URL.revokeObjectURL(localImageUrl.value)
const { blob, url } = await resizeImageFile(file, 512)
localImageUrl.value = url
const idx = availableImages.value.findIndex((img) => img.id === 'local-upload')
if (idx === -1) {
availableImages.value.unshift({ id: 'local-upload', url })
} else {
availableImages.value[idx].url = url
}
emit('add-image', {
id: 'local-upload',
url,
file: new File([blob], file.name, { type: 'image/png' }),
})
emit('update:modelValue', 'local-upload')
updateLocalImage(url, new File([blob], file.name, { type: 'image/png' }))
}
}
@@ -100,14 +89,7 @@ const confirmPhoto = async () => {
const { blob, url } = await resizeImageFile(originalBlob, 512)
localImageUrl.value = url
cameraFile.value = new File([blob], 'camera.png', { type: 'image/png' })
const idx = availableImages.value.findIndex((img) => img.id === 'local-upload')
if (idx === -1) {
availableImages.value.unshift({ id: 'local-upload', url })
} else {
availableImages.value[idx].url = url
}
emit('add-image', { id: 'local-upload', url, file: cameraFile.value })
emit('update:modelValue', 'local-upload')
updateLocalImage(url, cameraFile.value)
}
closeCamera()
}
@@ -125,6 +107,9 @@ const closeCamera = () => {
cameraStream.value.getTracks().forEach((track) => track.stop())
cameraStream.value = null
}
if (cameraVideo.value) {
cameraVideo.value.srcObject = null
}
}
const resumeCameraStream = async () => {
@@ -204,6 +189,17 @@ async function resizeImageFile(
URL.revokeObjectURL(url)
return { blob, url: URL.createObjectURL(blob) }
}
function updateLocalImage(url: string, file: File) {
const idx = availableImages.value.findIndex((img) => img.id === 'local-upload')
if (idx === -1) {
availableImages.value.unshift({ id: 'local-upload', url })
} else {
availableImages.value[idx].url = url
}
emit('add-image', { id: 'local-upload', url, file })
emit('update:modelValue', 'local-upload')
}
</script>
<template>
@@ -248,20 +244,20 @@ async function resizeImageFile(
<!-- Camera modal -->
<div v-if="showCamera" class="modal-backdrop">
<div class="modal camera-modal">
<h3>Take a Photo</h3>
<div v-if="cameraError" class="camera-error">{{ cameraError }}</div>
<h3>Take a photo</h3>
<div v-if="cameraError" class="error">{{ cameraError }}</div>
<div v-else>
<div v-if="!capturedImageUrl">
<video ref="cameraVideo" autoplay playsinline class="camera-video"></video>
<video ref="cameraVideo" autoplay playsinline class="camera-display"></video>
<div class="actions">
<button type="button" class="btn btn-primary" @click="takePhoto">Take Photo</button>
<button type="button" class="btn btn-primary" @click="takePhoto">Capture</button>
<button type="button" class="btn btn-secondary" @click="closeCamera">Cancel</button>
</div>
</div>
<div v-else>
<img :src="capturedImageUrl" class="captured-preview" alt="Preview" />
<img :src="capturedImageUrl" class="camera-display" alt="Preview" />
<div class="actions">
<button type="button" class="btn btn-primary" @click="confirmPhoto">Use Photo</button>
<button type="button" class="btn btn-primary" @click="confirmPhoto">Choose</button>
<button type="button" class="btn btn-secondary" @click="retakePhoto">Retake</button>
</div>
</div>
@@ -357,90 +353,12 @@ async function resizeImageFile(
padding-bottom: 1.5rem;
text-align: center;
}
.camera-header {
padding: 1rem;
border-bottom: 1px solid #e6e6e6;
display: flex;
justify-content: space-between;
align-items: center;
}
.camera-body {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.camera-error {
color: #ff4d4f;
margin-bottom: 1rem;
}
.camera-video {
width: 100%;
max-width: 320px;
border-radius: 12px;
background: #222;
margin-bottom: 1rem;
}
.camera-actions {
padding: 0.8rem 1rem;
display: flex;
justify-content: center;
gap: 1rem;
}
.btn.capture {
background: #667eea;
color: white;
flex: 1;
}
.btn.capture:hover {
background: #5a67d8;
}
.btn.confirm {
background: #28a745;
color: white;
flex: 1;
}
.btn.confirm:hover {
background: #218838;
}
.actions {
display: flex;
gap: 0.7rem;
justify-content: center;
margin-top: 0.5rem;
}
.btn {
padding: 0.5rem 1.1rem;
border-radius: 8px;
border: 0;
cursor: pointer;
font-weight: 700;
font-size: 1rem;
transition: background 0.18s;
}
.btn.cancel {
background: #f3f3f3;
color: #666;
}
.btn.save {
background: #667eea;
color: white;
}
.btn.save:hover {
background: #5a67d8;
}
.captured-preview {
.camera-display {
width: auto;
max-width: 100%;
max-height: 240px;
border-radius: 12px;
margin-bottom: 1rem;
display: block;
margin-left: auto;
margin-right: auto;