Skip to content

Commit

Permalink
feat:add validation for intro page
Browse files Browse the repository at this point in the history
  • Loading branch information
soheilsalimidev committed Jun 2, 2024
1 parent eb6bf48 commit e9138eb
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 116 deletions.
1 change: 1 addition & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ declare module 'vue' {
Frame: typeof import('./src/components/frame.vue')['default']
IntroFrame: typeof import('./src/components/frames/introFrame.vue')['default']
IntroPage: typeof import('./src/components/steps/introPage.vue')['default']
IntroPageItem: typeof import('./src/components/introPageItem.vue')['default']
ListItemMaker: typeof import('./src/components/ListItemMaker.vue')['default']
Menu: typeof import('@headlessui/vue')['Menu']
MenuButton: typeof import('@headlessui/vue')['MenuButton']
Expand Down
2 changes: 1 addition & 1 deletion src/components/Inputs/fileSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<div ref="dropZoneRef" class="flex items-center justify-center w-full grow">
<label
v-if="!preview"
class="flex flex-col rounded-lg border-4 border-dashed w-full p-10 group text-center h-full"
class="flex flex-col rounded-lg border-4 border-dashed w-full group text-center h-full"
>
<div
class="h-full w-full text-center flex flex-col items-center justify-center"
Expand Down
4 changes: 2 additions & 2 deletions src/components/frame.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<template>
<div class="flex flex-col">
<div class="device device-google-pixel-6-pro">
<div class="device-frame">
<div class="device-frame overflow-clip">
<component
:is="activeComponentFrame"
:key="activeTabIndex"
class="min-w-full"
class="min-w-full overflow-hidden"
>
</component>
</div>
Expand Down
57 changes: 34 additions & 23 deletions src/components/frames/introFrame.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { computed } from "vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { appInfo, openedPageIndexIntro } = storeToRefs(useAppSettingStore());
const page = computed<IntroPage | undefined>(
() => appInfo.value.app_setting.introPage.pages[openedPageIndexIntro.value],
);
Expand All @@ -19,23 +18,43 @@ const getImage = computed(() => {
</script>

<template>
<div
v-if="page"
:style="{
backgroundImage: page?.background,
}"
class="h-full w-full overflow-hidden flex items-center justify-center flex-col pt-4"
>
<h3 class="text-slate-900 text-2xl font-bold mt-10">
{{ page?.title }}
</h3>
<img :src="getImage" />
<p class="text-slate-800 text-lg text-center">{{ page?.description }}</p>
<div class="relative h-full w-full">
<Transition
v-if="page"
enter-from-class="translate-x-[100%]"
leave-active-class="translate-x-[150%]"
enter-active-class="transition duration-500"
mode="out-in"
>
<div
:key="openedPageIndexIntro"
:style="{
backgroundImage: page?.background,
}"
class="h-full w-full overflow-hidden flex items-center justify-center flex-col pt-4"
>
<h3 class="text-slate-900 text-2xl font-bold mt-10">
{{ page?.title }}
</h3>
<img :src="getImage" />
<p class="text-slate-800 text-lg text-center">
{{ page?.description }}
</p>
</div>
</Transition>
<div
class="mt-auto flex flex-row-reverse justify-center items-center relative w-full gap-2 mb-2"
v-else
class="h-full w-full overflow-hidden flex items-center justify-center flex-col pt-4 from-teal-200 to-teal-500 bg-gradient-135"
>
<h3 class="font-display text-lg font-bold p-3 text-center text-slate-900">
{{ t("selectPage") }}
</h3>
</div>
<div
class="mt-auto flex flex-row-reverse justify-center items-center absolute w-full gap-2 mb-2 bottom-2"
>
<span
class="h-2 w-2 border-white border rounded-full"
class="h-2 w-2 border-white border rounded-full transition duration-300"
v-for="(_, index) in appInfo.app_setting.introPage.pages"
:class="index === openedPageIndexIntro && 'bg-white'"
></span>
Expand All @@ -44,14 +63,6 @@ const getImage = computed(() => {
>
</div>
</div>
<div
v-else
class="h-full w-full overflow-hidden flex items-center justify-center flex-col pt-4 from-teal-200 to-teal-500 bg-gradient-135"
>
<h3 class="font-display text-lg font-bold p-3 text-center text-slate-900">
{{ t("selectPage") }}
</h3>
</div>
</template>
<i18n>
Expand Down
120 changes: 120 additions & 0 deletions src/components/introPageItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<template>
<checkboxItem
disable-checkbox
:open="openedPageIndexIntro === index"
@update:open="
$event ? (openedPageIndexIntro = index) : (openedPageIndexIntro = -1)
"
:error="v$.$error ? t('error') : ''"
class="w-full h-fit"
:label="t('page', { page: index + 1 })"
>
<template #end="">
<HeroiconsXMark
class="w-8 h-8 text-slate-700 dark:text-slate-200"
@click="removePage(index)"
/>
</template>

<template #description="">
{{ openedPageIndexIntro !== index ? t("pageInfo", page as any) : "" }}
</template>
<template #default="">
<div class="grid grid-cols-12 gap-4">
<textInput
v-model="page.title"
class="col-span-5"
:error="v$.title.$errors.map((e) => e.$message).join(',')"
label-class="dark:!bg-slate-700"
input-class="dark:!bg-slate-700"
:placeholder="t('pageTitle')"
:label="t('pageTitleHint')"
>
</textInput>
<textInput
v-model="page.description"
class="col-span-7"
:error="v$.description.$errors.map((e) => e.$message).join(',')"
label-class="dark:!bg-slate-700"
input-class="dark:!bg-slate-700"
:placeholder="t('pageDescriptionHint')"
:label="t('pageDescription')"
>
</textInput>

<color-picker
label-class="dark:!bg-slate-700"
input-class="dark:!bg-slate-700"
class="col-span-9"
v-model="page.background"
:error="v$.background.$errors.map((e) => e.$message).join(',')"
:label="$t('steps.splash_screeen_setting.select_your_color')"
>
</color-picker>

<FileSelect
class="col-span-12 h-40"
v-model="page.imageName"
:error="v$.imageName.$errors.map((e) => e.$message).join(',')"
:file-name="`pageImage${index}`"
:label="$t('steps.splash_screeen_setting.image')"
>
</FileSelect>
</div>
</template>
</checkboxItem>
</template>

<script setup lang="ts">
import { useI18n } from "vue-i18n";
import { IntroPage, useAppSettingStore } from "@/stores/appSetting";
import HeroiconsXMark from "~icons/heroicons/x-mark";
import { storeToRefs } from "pinia";
import useVuelidate from "@vuelidate/core";
import { useI18nValidators } from "@/utils/i18n-validators";
const { required } = useI18nValidators();
const { t } = useI18n();
const { appInfo, openedPageIndexIntro } = storeToRefs(useAppSettingStore());
const props = defineProps<{
page: IntroPage;
index: number;
}>();
const removePage = (index: number) => {
appInfo.value.app_setting.introPage.pages.splice(index, 1);
if (appInfo.value.app_setting.introPage.pages.length === 0)
appInfo.value.app_setting.introPage.enable = false;
};
const rules = {
title: {
required,
},
description: {
required,
},
background: {
required,
},
imageName: {
required,
},
};
const v$ = useVuelidate(rules, props.page);
</script>

<i18n>
{
"en":{
"pageInfo":"Page with title '{title}' and description of '{description}'",
"pageTitleHint":"Enter the page title",
"pageTitle":"Page title",
"pageDescriptionHint":"Enter the page description",
"pageDescription":"Page description",
"page":"Page {page}",
"error":"there is error in this item"
}
}
</i18n>
2 changes: 1 addition & 1 deletion src/components/steps.vue
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ const previous = () => {
};
const next = async () => {
if (await v$.value.$validate() || import.meta.env.DEV) {
if (await v$.value.$validate() ) {
tabDirectionXyzRight.value = true;
steps.value.find((step) => step.status === "current")!.status = "complete";
steps.value[++currentTab.value].status = "current";
Expand Down
104 changes: 15 additions & 89 deletions src/components/steps/introPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,13 @@
<span
class="text-slate-800 dark:text-slate-200 mb-10 text-center text-base"
>
Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit
enim labore culpa sint ad nisi Lorem pariatur mollit ex esse
exercitation amet. Nisi anim cupidatat excepteur officia.
Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate
voluptate dolor minim nulla est proident. Nostrud officia pariatur ut
officia. Sit irure elit esse ea nulla sunt ex
{{ t("introExplain") }}
</span>
<div class="flex items-center mb-5 justify-center">
<label
for="pageIntro"
class="me-2 text-lg font-bold text-gray-900 dark:text-gray-300 font-display"
>I need Intro</label
>{{ t("needIntro") }}</label
>
<input
id="pageIntro"
Expand Down Expand Up @@ -49,77 +44,17 @@
leave-to-class="translate-x-[150%] opacity-0"
leave-active-class="transition duration-300"
>
<checkboxItem
<IntroPageItem
v-for="(page, index) in appInfo.app_setting.introPage.pages"
disable-checkbox
:key="index"
:open="openedPageIndexIntro === index"
@update:open="
$event
? (openedPageIndexIntro = index)
: (openedPageIndexIntro = -1)
"
class="w-full h-fit"
:label="t('page', { page: index + 1 })"
>
<template #end="">
<HeroiconsXMark
class="w-8 h-8 text-slate-700 dark:text-slate-200"
@click="removePage(index)"
/>
</template>

<template #description="">
{{ openedPageIndexIntro !== index ? t("pageInfo", page) : "" }}
</template>
<template #default="">
<div class="grid grid-cols-12 gap-4">
<textInput
v-model="page.title"
class="col-span-5"
label-class="dark:!bg-slate-700"
input-class="dark:!bg-slate-700"
:placeholder="t('pageTitle')"
:label="t('pageTitleHint')"
>
</textInput>
<textInput
v-model="page.description"
class="col-span-7"
label-class="dark:!bg-slate-700"
input-class="dark:!bg-slate-700"
:placeholder="t('pageDescriptionHint')"
:label="t('pageDescription')"
>
</textInput>

<color-picker
label-class="dark:!bg-slate-700"
input-class="dark:!bg-slate-700"
class="col-span-9"
v-model="page.background"
:label="
$t('steps.splash_screeen_setting.select_your_color')
"
>
</color-picker>

<FileSelect
class="col-span-12 h-40"
v-model="page.imageName"
:file-name="`pageImage${index}`"
:label="$t('steps.splash_screeen_setting.image')"
>
</FileSelect>
</div>
</template>
</checkboxItem>
:page
:index
/>
</TransitionGroup>
</div>

<button
v-if="appInfo.app_setting.introPage.enable"
class="text-gray-900 dark:text-slate-100 rounded-3xl px-2 max-w-40 py-2 text-base font-medium bottom-4 end-4 absolute bg-indigo-500 flex justify-center items-center gap-2 group transition-all duration-500 ease-in-out"
class="text-gray-900 dark:text-slate-100 rounded-3xl px-2 max-w-16 hover:max-w-40 py-2 text-base font-medium bottom-4 end-4 absolute bg-indigo-500 flex justify-center items-center gap-2 group transition-all duration-500 ease-in-out"
@click="
appInfo.app_setting.introPage.pages.push({
title: '',
Expand All @@ -130,7 +65,7 @@
})
"
>
<span class="group-hover:block hidden"> Add more </span>
<span class="group-hover:block hidden min-w-20"> Add more </span>
<HeroiconsPlus16Solid class="w-8 h-8" />
</button>
</div>
Expand All @@ -139,31 +74,22 @@
</template>

<script setup lang="ts">
import { useAppSettingStore } from "@/stores/appSetting";
import { storeToRefs } from "pinia";
import { useI18n } from "vue-i18n";
import HeroiconsPlus16Solid from "~icons/heroicons/plus-16-solid";
import HeroiconsXMark from "~icons/heroicons/x-mark";
const { appInfo, openedPageIndexIntro } = storeToRefs(useAppSettingStore());
import { useAppSettingStore } from "@/stores/appSetting";
import { storeToRefs } from "pinia";
import IntroPageItem from "../introPageItem.vue";
const { t } = useI18n();
const { appInfo } = storeToRefs(useAppSettingStore());
const removePage = (index: number) => {
appInfo.value.app_setting.introPage.pages.splice(index, 1);
if (appInfo.value.app_setting.introPage.pages.length === 0)
appInfo.value.app_setting.introPage.enable = false;
};
const { t } = useI18n();
</script>

<i18n>
{
"en":{
"pageInfo":"Page with title '{title}' and description of '{description}'",
"pageTitleHint":"Enter the page title",
"pageTitle":"Page title",
"pageDescriptionHint":"Enter the page description",
"pageDescription":"Page description",
"page":"Page {page}"
"introExplain":"Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.",
"needIntro":"I need intro",
}
}
</i18n>

0 comments on commit e9138eb

Please sign in to comment.