Adds PhotoAlbum, CreatorHome, AboutCreator.

This commit is contained in:
2025-04-23 17:45:09 -04:00
parent 247b2b023c
commit 6d3525c2ee
42 changed files with 3176 additions and 818 deletions

View File

@@ -0,0 +1,262 @@
<template>
<div class="album-editor">
<h2 class="text-xl font-semibold mb-4">{{ t('creator.sections.album.title') }}</h2>
<div class="image-grid">
<!-- Upload button -->
<div class="image-wrapper upload-wrapper" @click="triggerFileInput">
<input
type="file"
ref="fileInput"
@change="handleFileUpload"
accept="image/*"
multiple
class="hidden"
/>
<div class="upload-content">
<v-icon size="large">mdi-plus</v-icon>
<span class="text-sm mt-2">{{ t('upload') }}</span>
</div>
</div>
<!-- Draggable images -->
<draggable
v-model="localImages"
class="image-grid"
item-key="id"
@end="handleReorder"
>
<template #item="{ element, index }">
<div class="image-wrapper">
<img :src="element.url" :alt="'Image ' + (index + 1)" />
<div class="image-actions">
<button @click="deleteImage(index)" class="action-btn delete-btn" :title="t('delete')">
<v-icon>mdi-delete</v-icon>
</button>
<button @click="moveImage(index, 'up')"
class="action-btn move-btn"
:disabled="index === 0"
:title="t('moveUp')">
<v-icon>mdi-arrow-up</v-icon>
</button>
<button @click="moveImage(index, 'down')"
class="action-btn move-btn"
:disabled="index === localImages.length - 1"
:title="t('moveDown')">
<v-icon>mdi-arrow-down</v-icon>
</button>
</div>
</div>
</template>
</draggable>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { useI18n } from 'vue-i18n';
import draggable from 'vuedraggable';
const props = defineProps({
images: {
type: Array,
required: true
}
});
const emit = defineEmits(['update:images']);
const { t } = useI18n();
const fileInput = ref(null);
// Local copy of images with IDs for drag and drop
const localImages = ref([]);
onMounted(() => {
// Initialize local images with IDs
localImages.value = props.images.map((url, index) => ({
id: index,
url: url
}));
});
// Trigger file input click
function triggerFileInput() {
fileInput.value.click();
}
// Handle file upload
async function handleFileUpload(event) {
const files = Array.from(event.target.files);
for (const file of files) {
if (file.type.startsWith('image/')) {
try {
// Create a data URL for preview
const reader = new FileReader();
reader.onload = (e) => {
const newImage = {
id: Date.now() + Math.random(), // Unique ID
url: e.target.result
};
localImages.value.push(newImage);
emit('update:images', localImages.value.map(img => img.url));
};
reader.readAsDataURL(file);
} catch (error) {
console.error('Error uploading image:', error);
}
}
}
// Reset file input
event.target.value = '';
}
// Delete an image
function deleteImage(index) {
localImages.value.splice(index, 1);
emit('update:images', localImages.value.map(img => img.url));
}
// Move image up or down
function moveImage(index, direction) {
const newIndex = direction === 'up' ? index - 1 : index + 1;
if (newIndex >= 0 && newIndex < localImages.value.length) {
const temp = localImages.value[index];
localImages.value[index] = localImages.value[newIndex];
localImages.value[newIndex] = temp;
emit('update:images', localImages.value.map(img => img.url));
}
}
// Handle reorder after drag and drop
function handleReorder() {
emit('update:images', localImages.value.map(img => img.url));
}
</script>
<style scoped>
.album-editor {
@apply w-full;
}
.image-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.5rem;
width: 100%;
}
.image-wrapper {
position: relative;
width: 100%;
aspect-ratio: 1;
overflow: hidden;
}
.upload-wrapper {
border: 2px dashed #ccc;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
}
.upload-wrapper:hover {
border-color: #666;
background-color: #f5f5f5;
}
.upload-content {
display: flex;
flex-direction: column;
align-items: center;
color: #666;
}
.image {
width: 100%;
height: 100%;
object-fit: cover;
}
.image-actions {
position: absolute;
top: 0;
right: 0;
display: flex;
gap: 0.25rem;
padding: 0.25rem;
background: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: opacity 0.3s ease;
}
.image-wrapper:hover .image-actions {
opacity: 1;
}
.action-btn {
background: none;
border: none;
color: white;
cursor: pointer;
padding: 0.25rem;
border-radius: 4px;
transition: background-color 0.2s;
}
.action-btn:hover {
background-color: rgba(255, 255, 255, 0.2);
}
.action-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Responsive adjustments */
@media (min-width: 768px) {
.image-grid {
grid-template-columns: repeat(4, 1fr);
}
}
@media (min-width: 1024px) {
.image-grid {
grid-template-columns: repeat(5, 1fr);
}
}
@media (max-width: 640px) {
.image-grid {
gap: 0.25rem;
}
}
</style>
<i18n>
{
"en": {
"upload": "Upload Photos",
"delete": "Delete",
"moveUp": "Move Up",
"moveDown": "Move Down"
},
"fr": {
"upload": "Télécharger des photos",
"delete": "Supprimer",
"moveUp": "Déplacer vers le haut",
"moveDown": "Déplacer vers le bas"
},
"es": {
"upload": "Subir fotos",
"delete": "Eliminar",
"moveUp": "Mover arriba",
"moveDown": "Mover abajo"
}
}
</i18n>