Commit 2a1a23c3 authored by Дмитрий Малюгин's avatar Дмитрий Малюгин 🕓
Browse files

finished with paragraph settings and refactor

parent 6cd608fd
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -35,6 +35,15 @@
  --orange-700: #c2410c;
  --orange-800: #9a3412;
  --orange-900: #7c2d12;
  --amber-100: #fef3c7;
  --amber-200: #fde68a;
  --amber-300: #fcd34d;
  --amber-400: #fbbf24;
  --amber-500: #f59e0b;
  --amber-600: #d97706;
  --amber-700: #b45309;
  --amber-800: #92400e;
  --amber-900: #78350f;
  --yellow-100: #fef9c3;
  --yellow-200: #fef08a;
  --yellow-300: #fde047;
@@ -283,3 +292,25 @@ input[type=file]::-webkit-file-upload-button {
    transform: scale(1);
  }
}
.v-enter-active,
.v-leave-active {
  transition: all 0.5s ease;
}
.fading-enter-active,
.fading-leave-active {
  transition: opacity 0.3s ease-in-out;
}
.fading-enter-active {
  animation: fading-in 0.5s;
}
.fading-leave-active {
  animation: fading-in 0.5s reverse;
}
@keyframes fading-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
+3 −0
Original line number Diff line number Diff line
@@ -46,9 +46,12 @@ declare module 'vue' {
    PageHeader: typeof import('./../modules/PageHeader.vue')['default']
    PageMenuButton: typeof import('./../components/PageMenuButton.vue')['default']
    ParagraphIcon: typeof import('./../shared/icons/ParagraphIcon.vue')['default']
    ParagraphItem: typeof import('./../modules/entities/ParagraphItem.vue')['default']
    ParagraphSettings: typeof import('./../components/entities/settings/ParagraphSettings.vue')['default']
    PlusIcon: typeof import('./../shared/icons/PlusIcon.vue')['default']
    RouterLink: typeof import('vue-router')['RouterLink']
    RouterView: typeof import('vue-router')['RouterView']
    SaveIcon: typeof import('./../shared/icons/SaveIcon.vue')['default']
    SettingsIcon: typeof import('./../shared/icons/SettingsIcon.vue')['default']
    SheetPage: typeof import('./../pages/[uuid]/SheetPage.vue')['default']
    SidebarMenuContent: typeof import('./../modules/SidebarMenuContent.vue')['default']
+45 −0
Original line number Diff line number Diff line
@@ -100,6 +100,8 @@ export const convertThemeToColorWhiteDefault = (theme: string | undefined) => {
      return '#22c55e';
    case 'yellow':
      return '#eab308';
    case 'amber':
      return '#f59e0b';
    case 'orange':
      return '#f97316';
    case 'pink':
@@ -120,6 +122,47 @@ export const convertThemeToColorWhiteDefault = (theme: string | undefined) => {
  return '#ffffff';
};

export const convert800ThemeToColorGrayDefault = (theme: string | undefined) => {
  if (!theme) return '#9294a1';
  switch (theme) {
    case 'white':
      return '#ffffff';
    case 'slate':
      return '#1e293b';
    case 'blue':
      return '#1e40af';
    case 'sky':
      return '#075985';
    case 'teal':
      return '#115e59';
    case 'lime':
      return '#3f6212';
    case 'green':
      return '#166534';
    case 'yellow':
      return '#854d0e';
    case 'amber':
      return '#92400e';
    case 'orange':
      return '#9a3412';
    case 'pink':
      return '#9d174d';
    case 'fuchsia':
      return '#86198f';
    case 'purple':
      return '#6b21a8';
    case 'indigo':
      return '#3730a3';
    case 'rose':
      return '#9f1239';
    case 'red':
      return '#991b1b';
    case 'black':
      return '#000000';
  }
  return '#9294a1';
};

export const convertThemeToColorBlackDefault = (theme: string | undefined) => {
  if (!theme) return '#000000';
  switch (theme) {
@@ -139,6 +182,8 @@ export const convertThemeToColorBlackDefault = (theme: string | undefined) => {
      return '#22c55e';
    case 'yellow':
      return '#eab308';
    case 'amber':
      return '#f59e0b';
    case 'orange':
      return '#f97316';
    case 'pink':
+1 −4
Original line number Diff line number Diff line
@@ -38,12 +38,10 @@ export interface IEntity {
}

export type TTheme =
  | 'white'
  | 'slate'
  | 'blue'
  | 'sky'
  | 'teal'
  | 'lime'
  | 'green'
  | 'yellow'
  | 'orange'
@@ -52,5 +50,4 @@ export type TTheme =
  | 'purple'
  | 'indigo'
  | 'rose'
  | 'red'
  | 'black';
  | 'red';
+207 −0
Original line number Diff line number Diff line
<script setup lang="ts">
import { convertThemeToColorWhiteDefault, editEntity } from '@/app/helpers';
import type { IParagraph } from '@/app/interfaces/entities';
import type { TTheme } from '@/app/interfaces/environment';
import cookies from '@/app/plugins/Cookie';

interface Props {
  entityData: IParagraph;
}
const props = defineProps<Props>();
const emit = defineEmits(['saveChanges']);
const entityData = props.entityData;
let newEntityData = ref({ ...entityData });
const isModal = ref<boolean>(false);

const changeFontSize = (newSize: '16' | '20' | '24' | '40' | '64') => {
  entityData.font_size = newSize;
  editEntity({ ...entityData, font_size: newSize });
};
const themeColor: TTheme = cookies.get('favorite_color');
const themeColorConverted = convertThemeToColorWhiteDefault(themeColor);
const isTitle = ref(!!entityData.title);
const isEntityWidthFull = ref(entityData.paragraph_size === 'full');

const maxLines = computed(() => {
  if (isTitle.value) {
    return Math.floor(168 / 24);
  } else {
    return Math.floor(240 / 24);
  }
});
const entityPositionOptions = [
  {
    label: 'left',
    value: 0
  },
  {
    label: 'center',
    value: 1
  },
  {
    label: 'right',
    value: 2
  }
];
const entityTitlePositionOptions = [
  {
    label: 'left',
    value: 0
  },
  {
    label: 'center',
    value: 1
  },
  {
    label: 'right',
    value: 2
  }
];
const saveChanges = () => {
  const entityPosition = isEntityWidthFull.value ? 'full' : 'half';
  if (entityPosition !== entityData.entity_position) {
    newEntityData.value.paragraph_size = entityPosition;
  }
  if (isTitle.value !== !!entityData.title) {
    if (isTitle.value) {
      newEntityData.value.title = 'Title';
    } else {
      newEntityData.value.title = null;
    }
  }
  if (JSON.stringify(entityData) !== JSON.stringify(newEntityData.value)) {
    console.log('they are different, I will save it. New data:', newEntityData.value);
    emit('saveChanges', newEntityData.value);
  }
  console.log('newEntityData.value :', newEntityData.value);
  isModal.value = false;
};
</script>

<template>
  <button
    :style="`background-color: ${themeColorConverted}`"
    class="settings absolute left-2 top-0 transition-all select-none size-10 flex justify-center items-center rounded-full hover:brightness-75 cursor-pointer"
    @click.prevent="isModal = true"
  >
    <SettingsIcon color="white" size="25" />
  </button>
  <Modal v-model:isVisible="isModal" theme="black" width="70%"
    ><template #header><h3 class="w-max mx-auto">Edit paragraph</h3></template>
    <div class="p-10 flex gap-16 items-center">
      <ul class="flex gap-8 h-full" style="min-width: 35%">
        <li class="flex flex-col items-center gap-4" style="min-width: 150px">
          <div>
            <p class="py-2 text-center">Title</p>
            <div class="flex items-center">
              Off
              <ToggleSwitch v-model:isActive="isTitle" class="mx-2" :theme="themeColor" />
              On
            </div>
          </div>
          <div style="height: 108px" class="flex gap-8 items-center justify-between col-span-2">
            <Transition name="fading">
              <div v-show="isTitle" class="flex flex-col items-center">
                <p class="py-2 text-center">Title position</p>
                <Slider
                  v-model:value="newEntityData.entity_title_position"
                  :theme="themeColor"
                  width="150"
                  size="small"
                  isSmooth="true"
                  backgroundColor="white"
                  min="0"
                  max="2"
                  step="1"
                  :options="entityTitlePositionOptions"
                />
              </div>
            </Transition>
          </div>
        </li>
        <li class="flex flex-col items-center gap-4" style="min-width: 150px">
          <div>
            <p class="py-2 text-center">Paragraph width</p>
            <div class="flex items-center">
              Half
              <ToggleSwitch
                v-model:isActive="isEntityWidthFull"
                class="mx-2"
                :theme="themeColor"
                :negativeTheme="themeColor"
              />
              Full
            </div>
          </div>
          <div style="height: 108px" class="flex gap-8 items-center justify-between col-span-2">
            <Transition name="fading">
              <div v-show="!isEntityWidthFull" class="flex flex-col items-center">
                <p class="py-2">Paragraph position</p>
                <Slider
                  v-model:value="newEntityData.entity_position"
                  :theme="themeColor"
                  width="150"
                  size="small"
                  isSmooth="true"
                  backgroundColor="white"
                  min="0"
                  max="2"
                  step="1"
                  :options="entityPositionOptions"
                />
              </div>
            </Transition>
          </div>
        </li>
      </ul>
      <section
        :style="`border-color: var(--${themeColor}-200); height: 320px`"
        class="grow flex flex-col gap-4 p-4 min-h-full border-2 border-slate-100 border-dashed rounded-2xl"
      >
        <h3
          v-show="isTitle"
          :style="`border-color: var(--${themeColor}-800); text-align: ${newEntityData.entity_title_position}`"
          class="text-2xl font-bold text-center px-2 py-4 border-2 border-dashed rounded-2xl"
        >
          {{ newEntityData.title ?? 'Title' }}
        </h3>
        <div :style="`justify-content: ${newEntityData.entity_position}`" class="grow flex">
          <div
            :style="`border-color: var(--${themeColor}-400); width: ${isEntityWidthFull ? '100%' : '50%'};`"
            class="h-full p-4 pb-2 border-2 border-dashed rounded-2xl overflow-hidden"
          >
            <p class="pb-0 overflow-hidden contain-inline-size text">{{ newEntityData.text }}</p>
          </div>
        </div>
      </section>
      <div class="absolute top-4 right-16 z-10 hover:brightness-80 transition-all">
        <Button label="Delete" textColor="white" theme="red" textStyle="bold" size="medium">
          <template #icon>
            <TrashIcon color="white" size="25" />
          </template>
        </Button>
      </div>
      <div
        class="absolute top-4 left-4 z-10 hover:brightness-80 transition-all"
        @click.prevent="saveChanges"
      >
        <Button label="Save" textColor="white" :theme="themeColor" textStyle="bold" size="medium">
          <template #icon>
            <SaveIcon color="white" size="25" />
          </template>
        </Button>
      </div>
    </div>
  </Modal>
</template>

<style scoped>
.text {
  --max-lines: v-bind(maxLines);
  overflow: hidden;

  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--max-lines);
}
</style>
Loading