146 lines
4.8 KiB
Vue
146 lines
4.8 KiB
Vue
<script lang="ts" setup>
|
|
import type { Calendar } from "~/models/CalendarConfig";
|
|
import { PhCircleNotch, PhWrench } from "@phosphor-icons/vue";
|
|
|
|
const props = defineProps<{
|
|
calendar: Calendar | null,
|
|
}>()
|
|
|
|
const calendarSkeleton = ref<Calendar>({ ...props.calendar } as Calendar)
|
|
|
|
onMounted(() => {
|
|
calendarSkeleton.value = { ...props.calendar } as Calendar
|
|
})
|
|
|
|
type FormTabs = "global" | "months" | "today"
|
|
const activeTab = ref<FormTabs>("global")
|
|
|
|
/**
|
|
* === Form Validation ===
|
|
*/
|
|
|
|
/** Whether the skeleton has valid month data */
|
|
const validSkeletonMonths = computed(() => calendarSkeleton.value.months.length > 0)
|
|
|
|
/** Whether the skeleton has a valid name */
|
|
const validSkeletonGeneral = computed(() => calendarSkeleton.value.name)
|
|
|
|
/** Whether all the data checks above are a-ok */
|
|
const validSkeleton = computed(() => validSkeletonGeneral.value && validSkeletonMonths.value)
|
|
|
|
/** Send the data to the store for validation */
|
|
const isUpdatingCalendar = ref<boolean>(false)
|
|
|
|
async function handleSubmit() {
|
|
try {
|
|
isUpdatingCalendar.value = true
|
|
await $fetch(`/api/calendars/${calendarSkeleton.value.id}`, { method: "PATCH", body: { ...calendarSkeleton.value, worldId: props.calendar?.world?.id } })
|
|
|
|
emit("on-close")
|
|
} catch (err) {
|
|
console.log(err)
|
|
} finally {
|
|
isUpdatingCalendar.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* === Watch for name changes to display above ===
|
|
*/
|
|
const emit = defineEmits<{
|
|
// eslint-disable-next-line no-unused-vars
|
|
(e: "on-changed-name", calendarName: string): void
|
|
// eslint-disable-next-line no-unused-vars
|
|
(e: "on-close"): void
|
|
}>()
|
|
|
|
/** Hook to emit a debounced event for the changed skeleton name */
|
|
const handleNameChange = useDebounceFn(() => {
|
|
emit("on-changed-name", calendarSkeleton.value.name)
|
|
}, 400)
|
|
|
|
function handleFormCancel() {
|
|
emit("on-close")
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<template v-if="calendarSkeleton">
|
|
<form class="h-full grid grid-rows-[1fr_auto]" @submit.prevent="handleSubmit">
|
|
<UiTabs v-model:model-value="activeTab">
|
|
<UiTabsList class="grid w-full grid-cols-1 mb-4">
|
|
<UiTabsTrigger value="global" class="font-bold">
|
|
<div class="flex items-center gap-1">
|
|
<PhWrench size="18" weight="fill" />
|
|
|
|
{{ $t('entity.calendar.actionDialog.tabs.general.title') }}
|
|
</div>
|
|
</UiTabsTrigger>
|
|
<!-- <UiTabsTrigger value="months" class="font-bold">
|
|
<div class="flex items-center gap-1">
|
|
<PhCalendarDots size="18" weight="fill" />
|
|
|
|
{{ $t('entity.calendar.actionDialog.tabs.months.title') }}
|
|
</div>
|
|
</UiTabsTrigger>
|
|
<UiTabsTrigger value="today" class="font-bold">
|
|
<div class="flex items-center gap-1">
|
|
<PhAlarm size="18" weight="fill" />
|
|
|
|
{{ $t('entity.calendar.actionDialog.tabs.today.title') }}
|
|
</div>
|
|
</UiTabsTrigger> -->
|
|
</UiTabsList>
|
|
<UiTabsContent value="global" class="grid gap-4">
|
|
<input
|
|
id="new-calendar-name"
|
|
v-model="calendarSkeleton.name"
|
|
type="text"
|
|
name="new-calendar-name"
|
|
required
|
|
:placeholder="$t('common.title')"
|
|
class="w-full py-2 -mx-1 px-1 text-xl border-b-[1px] bg-transparent focus-visible:outline-none focus-visible:border-blue-600"
|
|
@input="handleNameChange"
|
|
>
|
|
|
|
<div class="-mx-1 px-1 grid gap-3">
|
|
<UiLabel for="new-calendar-state">
|
|
{{ $t('ui.contentState.label') }}
|
|
</UiLabel>
|
|
|
|
<InputContentState id="new-calendar-state" v-model="calendarSkeleton.state" />
|
|
</div>
|
|
|
|
<div class="-mx-1 grid gap-3">
|
|
<UiLabel for="new-calendar-color">
|
|
{{ $t('ui.colors.label') }}
|
|
</UiLabel>
|
|
|
|
<InputColor id="new-calendar-color" v-model="calendarSkeleton.color" />
|
|
</div>
|
|
</UiTabsContent>
|
|
<!-- <UiTabsContent value="months">
|
|
<CalendarInputMonthList v-model:model-value="calendarSkeleton.months" />
|
|
</UiTabsContent>
|
|
<UiTabsContent value="today">
|
|
<CalendarInputTodaySelect v-model:model-value="calendarSkeleton.today" :available-months="calendarSkeleton.months"/>
|
|
</UiTabsContent> -->
|
|
</UiTabs>
|
|
|
|
<footer class="flex justify-end gap-2 mt-6">
|
|
<UiButton type="button" variant="destructive" @click="handleFormCancel">
|
|
{{ $t('ui.action.cancel') }}
|
|
</UiButton>
|
|
|
|
<UiButton type="submit" :disabled="!validSkeleton || isUpdatingCalendar">
|
|
<Transition name="fade">
|
|
<PhCircleNotch v-if="isUpdatingCalendar" size="20" class="opacity-50 animate-spin"/>
|
|
</Transition>
|
|
|
|
{{ $t('ui.action.save') }}
|
|
</UiButton>
|
|
</footer>
|
|
</form>
|
|
</template>
|
|
</template>
|