Added read only category table

This commit is contained in:
Alexis
2025-03-31 19:10:11 +02:00
parent d4d74db5d9
commit 8005a8e9a2
19 changed files with 440 additions and 92 deletions

View File

@@ -9,7 +9,7 @@ defineProps<{
<template>
<ul>
<li v-for="category in categories" :key="category.id">
<CalendarCategoryItem :category="category" />
<CalendarCategoryListItem :category="category" />
</li>
</ul>
</template>

View File

@@ -7,7 +7,9 @@ defineProps<{
</script>
<template>
<UiButton variant="secondary" size="sm" class="w-full text-left">
{{ category }}
</UiButton>
<div class="flex items-center gap-2">
<span class="text-sm text-gray-700 dark:text-gray-300">
{{ category.name }}
</span>
</div>
</template>

View File

@@ -0,0 +1,42 @@
<script setup lang="ts">
import type { Category } from "~/models/Category";
import { ScrollAreaRoot, ScrollAreaViewport, ScrollAreaScrollbar, ScrollAreaThumb } from "radix-vue"
defineProps<{
categories: Category[]
}>()
</script>
<template>
<div class="flex flex-col h-full">
<header class="grid grid-cols-12 gap-4 px-2 py-4 border-b-[1px] border-b-foreground/10 font-bold">
<div class="col-span-6">
Nom
</div>
<div class="col-span-4">
Couleur
</div>
<div class="col-span-2" />
</header>
<ScrollAreaRoot class="h-36 grow overflow-hidden ">
<ScrollAreaViewport class="w-full h-full pr-4" as-child>
<div class="[&:last-child]:border-0">
<CalendarCategoryTableRow
v-for="item in categories"
:key="item.id"
:category="item"
/>
</div>
</ScrollAreaViewport>
<ScrollAreaScrollbar
class="flex select-none touch-none p-0.5 bg-background transition-colors duration-100 ease-out hover:bg-foreground/5 data-[orientation=vertical]:w-2.5 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:h-2.5"
orientation="vertical"
>
<ScrollAreaThumb
class="flex-1 bg-foreground/20 rounded-[10px] relative before:content-[''] before:absolute before:top-1/2 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:w-full before:h-full"
/>
</ScrollAreaScrollbar>
</ScrollAreaRoot>
</div>
</template>

View File

@@ -0,0 +1,137 @@
<script setup lang="ts">
import { PhCheck } from "@phosphor-icons/vue";
import { cn } from "~/lib/utils";
import type { Category } from "~/models/Category";
const props = defineProps<{
category: Category
}>()
type RowMode = "edit" | "view";
const currentMode = ref<RowMode>("view");
const rowRef = ref<HTMLDivElement | null>(null);
const inputRef = ref<HTMLInputElement | null>(null);
const { focused: inputFocused } = useFocus(inputRef);
/**
* Toggle view mode options
*/
type ToggleViewOptions = {
execution?: "now" | "nextTick"
}
/**
* Toggle view mode
* @param options.execution - When to execute the toggle. "now" or "nextTick"
*/
function toggleView(options: ToggleViewOptions = { execution: "now" }) {
currentMode.value = "view";
categorySkeleton.value = structuredClone(toRaw(props.category));
if (options.execution === "now") {
inputFocused.value = false;
} else {
nextTick(() => {
inputFocused.value = false;
});
}
}
/**
* Toggle edit mode
*/
function toggleEdit() {
currentMode.value = "edit";
nextTick(() => {
inputFocused.value = true;
});
}
onClickOutside(rowRef, () => toggleView({ execution: "nextTick" }));
onKeyStroke("Escape", () => toggleView({ execution: "now" }));
const categorySkeleton = ref<Category>(structuredClone(toRaw(props.category)))
/**
* Submit the update
* TODO: Implement the update logic
*/
function submitUpdate() {
console.log("oui")
}
</script>
<template>
<div
ref="rowRef"
class="grid grid-cols-12 items-center gap-4 p-1"
:class="cn(
{ 'bg-slate-100 hover:bg-slate-200 dark:bg-slate-900 dark:hover:bg-slate-800': currentMode === 'edit' },
{ 'bg-transparent hover:bg-slate-50 dark:bg-transparent dark:hover:bg-slate-900': currentMode !== 'edit' }
)"
>
<div
class="col-span-6"
>
<template v-if="currentMode === 'view'">
<button
class="py-2 px-1 h-full w-full text-left underline-offset-4 hover:underline cursor-pointer"
@click="toggleEdit"
>
{{ category.name }}
</button>
</template>
<template v-else-if="currentMode === 'edit'">
<input
ref="inputRef"
type="text"
:value="category.name"
class="p-1 h-full w-full bg-transparent focus-visible:outline-none italic"
>
</template>
</div>
<div class="col-span-4">
<template v-if="currentMode === 'view'">
<button
class="p-1 h-full w-full text-left text-sm cursor-pointer"
@click="toggleEdit"
>
<span
class="bgc"
:class="cn(`bgc-${category.color}`)"
>
{{ $t(`ui.colors.${category.color}`) }}
</span>
</button>
</template>
<template v-else-if="currentMode === 'edit'">
<div class="-mx-2">
<InputColor
id="category-color"
v-model="categorySkeleton.color"
position="item-aligned"
theme="subtle"
/>
</div>
</template>
</div>
<div class="col-span-2">
<menu class="w-fit ml-auto">
<li>
<UiButton
v-if="currentMode === 'edit'"
variant="secondary"
size="icon"
class="w-6 h-6 rounded-full bg-emerald-500 hover:bg-emerald-600 text-white"
:to="{ name: 'calendar.category.edit', params: { id: category.id } }"
:title="$t('ui.actions.edit')"
@click="submitUpdate"
>
<PhCheck size="14" weight="bold" />
</UiButton>
</li>
</menu>
</div>
</div>
</template>

View File

@@ -13,10 +13,9 @@ function handleClosing() {
<template>
<UiAlertDialog :open="isCategoriesModalOpen">
<UiAlertDialogContent
class="grid grid-rows-[auto_1fr_auto] items-start min-h-[66vh] max-w-4xl gap-6"
class="grid grid-rows-[auto_1fr_auto] items-start min-h-[66vh] max-w-4xl"
:disable-outside-pointer-events="true"
:trap-focus="true"
@escape-key-down="handleClosing"
@focus-outside="handleClosing"
@interact-outside="handleClosing"
@close-auto-focus="(e) => e.preventDefault()"

View File

@@ -3,5 +3,5 @@ const { categories } = storeToRefs(useCalendar())
</script>
<template>
<CalendarCategoryList :categories />
<CalendarCategoryTable :categories />
</template>