Added basic event details

This commit is contained in:
Alexis
2024-04-02 20:38:59 +02:00
parent 5f8af0fa9e
commit 015509abf8
16 changed files with 204 additions and 54 deletions

View File

@@ -1,15 +1,29 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { Popover, PopoverTrigger } from '@/components/ui/popover'
import type { CalendarEvent } from '@/stores/events'
import CalendarEventDetails from './CalendarEventDetails.vue'
const props = defineProps<{
event: CalendarEvent
}>()
const eventTitleExcerpt = computed(() => {
if (props.event.title.length > 20) return props.event.title.substring(0, 20) + '…'
return props.event.title
})
</script>
<template>
<button
class="text-xs text-white px-2 py-1 bg-pink-700 block w-full text-left rounded-sm hover:bg-pink-800"
>
{{ event.title }}
</button>
<Popover>
<PopoverTrigger as-child>
<button
class="text-xs text-white px-2 py-1 bg-pink-700 block w-full text-left rounded-sm hover:bg-pink-800"
>
{{ eventTitleExcerpt }}
</button>
</PopoverTrigger>
<CalendarEventDetails :event />
</Popover>
</template>

View File

@@ -0,0 +1,25 @@
<script lang="ts" setup>
import { PopoverContent } from '@/components/ui/popover'
import { useCalendar } from '@/stores/calendar'
import type { CalendarEvent } from '@/stores/events'
const { getFormattedDateTitle } = useCalendar()
defineProps<{ event: CalendarEvent }>()
</script>
<template>
<PopoverContent class="w-96" align="start">
<div class="space-y-1">
<div class="font-semibold">
{{ event.title }}
</div>
<div class="text-sm">
{{ getFormattedDateTitle(event.date, true) }}
</div>
<div class="text-sm italic text-slate-500">
{{ event.description }}
</div>
</div>
</PopoverContent>
</template>

View File

@@ -28,7 +28,7 @@ const {
<div class="flex items-center gap-6">
<menu class="flex items-center gap-2">
<li>
<Button @click="jumpToDefaultDate"> Today </Button>
<Button @click="jumpToDefaultDate" size="sm"> Today </Button>
</li>
<li>
<!-- Implement decrementDate to account for other mods -->

View File

@@ -40,7 +40,7 @@ const isDefaultDate = computed(() => {
>{{ date.day }}</span
>
</div>
<ul v-if="eventsForTheDay.length > 0" class="grid gap-1">
<ul v-if="eventsForTheDay.length > 0" class="absolute top-12 bottom-0 inset-x-2 grid gap-1">
<li v-for="event in eventsForTheDay" :key="event.title">
<CalendarEvent :event />
</li>

View File

@@ -11,7 +11,7 @@ interface Props extends PrimitiveProps {
}
const props = withDefaults(defineProps<Props>(), {
as: 'button',
as: 'button'
})
</script>

View File

@@ -8,27 +8,24 @@ export const buttonVariants = cva(
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive:
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline:
'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
link: 'text-primary underline-offset-4 hover:underline'
},
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 rounded-md px-3',
sm: 'h-9 rounded-md px-3 text-sm',
lg: 'h-11 rounded-md px-8',
icon: 'h-10 w-10',
},
icon: 'h-10 w-10'
}
},
defaultVariants: {
variant: 'default',
size: 'default',
},
},
size: 'default'
}
}
)
export type ButtonVariants = VariantProps<typeof buttonVariants>

View File

@@ -0,0 +1,15 @@
<script setup lang="ts">
import { PopoverRoot, useForwardPropsEmits } from 'radix-vue'
import type { PopoverRootEmits, PopoverRootProps } from 'radix-vue'
const props = defineProps<PopoverRootProps>()
const emits = defineEmits<PopoverRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<PopoverRoot v-bind="forwarded">
<slot />
</PopoverRoot>
</template>

View File

@@ -0,0 +1,48 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import {
PopoverContent,
type PopoverContentEmits,
type PopoverContentProps,
PopoverPortal,
useForwardPropsEmits
} from 'radix-vue'
import { cn } from '@/lib/utils'
defineOptions({
inheritAttrs: false
})
const props = withDefaults(
defineProps<PopoverContentProps & { class?: HTMLAttributes['class'] }>(),
{
align: 'center',
sideOffset: 4
}
)
const emits = defineEmits<PopoverContentEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>
<template>
<PopoverPortal>
<PopoverContent
v-bind="{ ...forwarded, ...$attrs }"
:class="
cn(
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
props.class
)
"
>
<slot />
</PopoverContent>
</PopoverPortal>
</template>

View File

@@ -0,0 +1,11 @@
<script setup lang="ts">
import { PopoverTrigger, type PopoverTriggerProps } from 'radix-vue'
const props = defineProps<PopoverTriggerProps>()
</script>
<template>
<PopoverTrigger v-bind="props">
<slot />
</PopoverTrigger>
</template>

View File

@@ -0,0 +1,3 @@
export { default as Popover } from './Popover.vue'
export { default as PopoverTrigger } from './PopoverTrigger.vue'
export { default as PopoverContent } from './PopoverContent.vue'

View File

@@ -6,20 +6,20 @@ import {
type SelectContentProps,
SelectPortal,
SelectViewport,
useForwardPropsEmits,
useForwardPropsEmits
} from 'radix-vue'
import { SelectScrollDownButton, SelectScrollUpButton } from '.'
import { cn } from '@/lib/utils'
defineOptions({
inheritAttrs: false,
inheritAttrs: false
})
const props = withDefaults(
defineProps<SelectContentProps & { class?: HTMLAttributes['class'] }>(),
{
position: 'popper',
},
position: 'popper'
}
)
const emits = defineEmits<SelectContentEmits>()
@@ -35,16 +35,26 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
<template>
<SelectPortal>
<SelectContent
v-bind="{ ...forwarded, ...$attrs }" :class="cn(
'relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
position === 'popper'
&& 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
props.class,
)
v-bind="{ ...forwarded, ...$attrs }"
:class="
cn(
'relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
position === 'popper' &&
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
props.class
)
"
>
<SelectScrollUpButton />
<SelectViewport :class="cn('p-1', position === 'popper' && 'h-[--radix-select-trigger-height] w-full min-w-[--radix-select-trigger-width]')">
<SelectViewport
:class="
cn(
'p-1',
position === 'popper' &&
'h-[--radix-select-trigger-height] w-full min-w-[--radix-select-trigger-width]'
)
"
>
<slot />
</SelectViewport>
<SelectScrollDownButton />

View File

@@ -5,7 +5,7 @@ import {
SelectItemIndicator,
type SelectItemProps,
SelectItemText,
useForwardProps,
useForwardProps
} from 'radix-vue'
import { Check } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
@@ -27,7 +27,7 @@ const forwardedProps = useForwardProps(delegatedProps)
:class="
cn(
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
props.class,
props.class
)
"
>

View File

@@ -1,6 +1,10 @@
<script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { SelectScrollDownButton, type SelectScrollDownButtonProps, useForwardProps } from 'radix-vue'
import {
SelectScrollDownButton,
type SelectScrollDownButtonProps,
useForwardProps
} from 'radix-vue'
import { ChevronDown } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
@@ -16,7 +20,10 @@ const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<SelectScrollDownButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
<SelectScrollDownButton
v-bind="forwardedProps"
:class="cn('flex cursor-default items-center justify-center py-1', props.class)"
>
<slot>
<ChevronDown class="h-4 w-4" />
</slot>

View File

@@ -16,7 +16,10 @@ const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<SelectScrollUpButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
<SelectScrollUpButton
v-bind="forwardedProps"
:class="cn('flex cursor-default items-center justify-center py-1', props.class)"
>
<slot>
<ChevronUp class="h-4 w-4" />
</slot>

View File

@@ -18,10 +18,12 @@ const forwardedProps = useForwardProps(delegatedProps)
<template>
<SelectTrigger
v-bind="forwardedProps"
:class="cn(
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
props.class,
)"
:class="
cn(
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
props.class
)
"
>
<slot />
<SelectIcon as-child>

View File

@@ -104,26 +104,27 @@ export const useCalendar = defineStore('calendar', () => {
const currentMonth = computed(() => params.month)
// Gets the label from currentMonth index
const currentMonthName = computed(() => {
const index = Number(currentMonth.value)
return staticConfig.months[index]
})
const currentMonthName = computed(() => getMonthName(Number(currentMonth.value)))
const currentYear = computed(() => params.year)
// Get period from currentYear
const currentPeriod: ComputedRef<LeimPeriod> = computed(() => {
const year = Number(currentYear.value)
return year >= 0 ? 'nante' : 'ante'
})
const currentPeriodAbbr: ComputedRef<LeimPeriodShort> = computed(() => {
return currentPeriod.value === 'ante' ? 'A.R' : 'N.R'
})
const currentPeriod: ComputedRef<LeimPeriod> = computed(
() => getPeriodOfYear(Number(currentYear.value)).long
)
const currentPeriodAbbr: ComputedRef<LeimPeriodShort> = computed(
() => getPeriodOfYear(Number(currentYear.value)).short
)
const currentDateTitle = computed(() => {
switch (currentConfig.value.viewType) {
case 'month':
return `${currentMonthName.value} ${currentYear.value} ${currentPeriodAbbr.value}`
return getFormattedDateTitle({
day: Number(currentDate.currentDay.value),
month: Number(currentDate.currentMonth.value),
year: Number(currentDate.currentYear.value),
period: currentDate.currentPeriod.value
})
case 'year':
return `Année ${currentYear.value} ${currentPeriodAbbr.value}`
@@ -238,6 +239,19 @@ export const useCalendar = defineStore('calendar', () => {
}
}
function getMonthName(monthNumber: number) {
const index = Number(monthNumber)
return staticConfig.months[index]
}
function getFormattedDateTitle(date: LeimDate, showNumber?: boolean): string {
if (showNumber) {
return `${date.day} ${getMonthName(date.month)} ${date.year} ${getPeriodOfYear(date.year).short}`
}
return `${getMonthName(date.month)} ${date.year} ${getPeriodOfYear(date.year).short}`
}
function compareTwoDates(date1: LeimDate, date2: LeimDate) {
// To refacto to be more precise
return JSON.stringify({ ...date1 }) === JSON.stringify({ ...date2 })
@@ -265,6 +279,7 @@ export const useCalendar = defineStore('calendar', () => {
incrementYear,
decrementYear,
jumpToDefaultDate,
compareTwoDates
compareTwoDates,
getFormattedDateTitle
}
})