| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- <template>
- <div class="q-pa-md">
- <div class="row q-col-gutter-md">
- <!-- Coluna esquerda: lista -->
- <div class="col-12 col-md-5">
- <div class="row justify-between items-center q-mb-md">
- <span class="text-subtitle1 text-weight-medium">Mídias</span>
- <q-btn
- icon="add"
- color="primary-2"
- style="height: 40px; width: 40px; border-radius: 8px"
- :disable="!unitId"
- @click="openAddDialog"
- />
- </div>
- <div v-if="loading" class="row justify-center q-pa-xl">
- <q-spinner color="primary" size="40px" />
- </div>
- <template v-else>
- <div
- v-if="medias.length === 0"
- class="text-center text-grey-6 q-pa-xl"
- >
- <q-icon
- name="mdi-image-multiple-outline"
- size="48px"
- color="grey-4"
- />
- <div class="q-mt-sm">Nenhuma mídia adicionada.</div>
- </div>
- <q-list v-else separator>
- <q-item
- v-for="(item, index) in medias"
- :key="item.id"
- clickable
- :active="selectedIndex === index"
- active-class="media-item-active"
- @click="selectedIndex = index"
- >
- <q-item-section avatar>
- <q-icon
- :name="getFileIcon(item.mime_type)"
- :color="getFileColor(item.mime_type)"
- size="md"
- />
- </q-item-section>
- <q-item-section>
- <q-item-label class="ellipsis" style="max-width: 180px">
- {{ item.title }}
- </q-item-label>
- <q-item-label caption>
- {{ formatDate(item.created_at) }}
- </q-item-label>
- </q-item-section>
- <q-item-section side />
- </q-item>
- </q-list>
- </template>
- </div>
- <!-- Coluna direita: pré-visualização -->
- <div class="col-12 col-md-7">
- <div class="preview-box">
- <div
- v-if="selectedIndex === null || !medias[selectedIndex]"
- class="flex flex-center full-height text-grey-5"
- style="min-height: 500px"
- >
- <div class="column items-center q-gutter-sm">
- <q-icon
- name="mdi-image-multiple-outline"
- size="64px"
- color="grey-3"
- />
- <span>Selecione uma mídia para visualizar</span>
- </div>
- </div>
- <template v-else>
- <img
- v-if="isImage(medias[selectedIndex].mime_type)"
- :src="medias[selectedIndex].file_url"
- style="width: 100%; border-radius: 8px; display: block"
- />
- <video
- v-else-if="isVideo(medias[selectedIndex].mime_type)"
- :src="medias[selectedIndex].file_url"
- controls
- style="width: 100%; border-radius: 8px; display: block"
- />
- <iframe
- v-else
- :src="medias[selectedIndex].file_url"
- style="
- width: 100%;
- min-height: 500px;
- border: none;
- border-radius: 8px;
- "
- />
- </template>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, onMounted } from "vue";
- import { useQuasar } from "quasar";
- import { getMediasByUnit } from "src/api/unit_media";
- import AddMediaDialog from "src/pages/unit/components/AddMediaDialog.vue";
- const props = defineProps({
- unitId: { type: Number, default: null },
- });
- const $q = useQuasar();
- const medias = ref([]);
- const selectedIndex = ref(null);
- const loading = ref(false);
- async function fetchMedias() {
- if (!props.unitId) return;
- loading.value = true;
- try {
- medias.value = await getMediasByUnit(props.unitId);
- } catch (e) {
- console.error(e);
- } finally {
- loading.value = false;
- }
- }
- function openAddDialog() {
- $q.dialog({
- component: AddMediaDialog,
- componentProps: { unitId: props.unitId },
- }).onOk((result) => {
- medias.value.unshift(result);
- selectedIndex.value = 0;
- });
- }
- function isImage(mimeType) {
- return mimeType?.startsWith("image/");
- }
- function isVideo(mimeType) {
- return mimeType?.startsWith("video/");
- }
- function getFileIcon(mimeType) {
- if (isImage(mimeType)) return "mdi-image-outline";
- if (isVideo(mimeType)) return "mdi-video-outline";
- return "mdi-file-pdf-box";
- }
- function getFileColor(mimeType) {
- if (isImage(mimeType)) return "teal";
- if (isVideo(mimeType)) return "blue";
- return "negative";
- }
- function formatDate(dateStr) {
- if (!dateStr) return "";
- return new Date(dateStr).toLocaleDateString("pt-BR");
- }
- onMounted(fetchMedias);
- </script>
- <style scoped>
- .preview-box {
- border: 1px solid #e0e0e0;
- border-radius: 8px;
- overflow: hidden;
- min-height: 500px;
- }
- .media-item-active {
- background-color: rgba(255, 131, 64, 0.08);
- }
- .ellipsis {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- </style>
|