Skip to content
Snippets Groups Projects
ImageItem.vue 4.69 KiB
Newer Older
<script setup lang="ts">
import { useVModel, useWindowSize } from '@vueuse/core';
import type { IImage } from '@/app/interfaces/entities';
import { editEntity } from '@/app/helpers';
import { cropImage } from '@/app/helpers/images';

interface Props {
  entityData: IImage;
}
const props = defineProps<Props>();
const emit = defineEmits(['update:entityData']);
const entityData = useVModel(props, 'entityData', emit);

const isModalCropImage = ref<boolean>(false);
const { width: windowWidth } = useWindowSize();

const textContainerWidth = computed(() => {
  if (entityData.value?.paragraph_size === 'half')
    return (windowWidth.value - 160 - entityData.value.image_width) / 2;
  return windowWidth.value - 160 - entityData.value.image_width;

const editTitle = () => {
  editEntity({ ...entityData.value, title: entityData.value.title });
};
const editText = () => {
  editEntity({ ...entityData.value, text: entityData.value.text });
const saveImage = async (newUrl: string, newWidth: number, newHeight: number) => {
  entityData.value.imageUrl = newUrl;
  entityData.value.image_width = newWidth;
  entityData.value.image_height = newHeight;
  await cropImage(newUrl, entityData.value);
  isModalCropImage.value = false;
};
const scaleImage = (scale: string) => {
  const initialWidth = Math.ceil(entityData.value.image_width / +entityData.value.image_scale);
  entityData.value.image_width = initialWidth * +scale;
  const initialHeight = Math.ceil(entityData.value.image_height / +entityData.value.image_scale);
  entityData.value.image_height = initialHeight * +scale;
  entityData.value.image_scale = scale;
  editEntity({ ...entityData.value });
};
const openCropImageModal = () => (isModalCropImage.value = true);
      'entityContainer relative flex px-16 transition-all',
        'justify-start': entityData.entity_position === 'left',
        'justify-center': entityData.entity_position === 'center',
        'justify-end': entityData.entity_position === 'right'
    <CropImageModal
      v-model:isVisible="isModalCropImage"
      v-model:imageInfo="entityData"
      @saveImage="saveImage"
    />
    <div class="flex flex-col">
      <EntityTitle
        v-model:title="entityData.title"
        :entityData="entityData"
        :isEditMode="isEditMode"
        @editTitle="editTitle"
      <div style="gap: 32px" class="flex" :style="`height: ${entityData.image_height}px`">
        <div
          :class="[
            'imageContainer relative leading-none',
            {
              'order-3': entityData.text_position === 'left'
            }
          ]"
          :style="`width: ${entityData.image_width}px; height: ${entityData.image_height}px; min-width: 100px; min-height: 100px`"
            :src="entityData?.imageUrl"
            :alt="`Image ${entityData?.title}` || 'Image'"
            :width="entityData.image_width"
            :height="entityData.image_height"
            style="min-height: 100px; max-height: 700px"
            class="object-contain order-1"
          />
          <div class="speedDialSize absolute left-0 top-0 transition-all select-none">
            <ImageSizeMenu v-if="isEditMode" :entityData="entityData" @scaleImage="scaleImage" />
          </div>
        </div>
          v-if="entityData.text_position"
          class="textContainer relative leading-none"
          :style="`width: ${textContainerWidth}px; height: ${entityData.image_height}px`"
        >
          <textarea
            ref="textarea"
            v-model="entityData.text"
            :class="[
              'w-full indent-5 leading-normal overflow-auto resize-none outline-0 order-2',
              {
                'pointer-events-none': !isEditMode
              }
            ]"
            placeholder="Enter text..."
            rows="7"
            :style="`font-size: ${entityData.font_size}px; height: ${entityData.image_height}px;`"
            spellcheck="false"
        v-model:entityData="entityData"
        @openCropImageModal="openCropImageModal"
      />
      <EntityPositionSettings :entityUuid="entityData.entity_uuid" />
.entityContainer:hover .aggregateHigh {
  height: 65px;
.entityContainer:hover .aggregateShort {
  height: 30px;
.entityContainer .speedDial {
  opacity: 0;
}
.entityContainer:hover .speedDial {
  opacity: 100;
}
.imageContainer .speedDialSize {
  opacity: 0;
}
.imageContainer:hover .speedDialSize {
  opacity: 100;
}
input::placeholder {
  font-weight: 400;
}
</style>