frontend: run lint
Signed-off-by: Nicolas Froger <nicolas@kektus.xyz>
This commit is contained in:
parent
3d6a2991b1
commit
2647ac244d
61 changed files with 426 additions and 592 deletions
|
|
@ -1,134 +0,0 @@
|
|||
[
|
||||
{
|
||||
"id": 4,
|
||||
"date": "2022-07-01T22:20:43.000Z",
|
||||
"location": {
|
||||
"lat": 48.93071193154141,
|
||||
"lon": 2.1544736306563346,
|
||||
"city": "Sartrouville",
|
||||
"country": "France"
|
||||
},
|
||||
"description": "je suis en train de me prendre en photo dans la rue",
|
||||
"assets": [
|
||||
"https://www.kektus.fr/img/DSC09764.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"date": "2023-12-28T23:18:43.511Z",
|
||||
"location": {
|
||||
"lat": 45.8307086344589862,
|
||||
"lon": -1.107245822424634,
|
||||
"city": "Marennes-Hiers-Brouage",
|
||||
"country": "France"
|
||||
},
|
||||
"description": "ce mec est très dangereux",
|
||||
"assets": [
|
||||
"https://www.kektus.fr/img/DSC00671.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"date": "2024-07-21T18:25:43.511Z",
|
||||
"location": {
|
||||
"lat": 45.98963904301394,
|
||||
"lon": -1.3010006132332887,
|
||||
"city": "Saint-Georges-d'Oléron",
|
||||
"country": "France"
|
||||
},
|
||||
"description": "ceci est une **plage** avec un très long texte.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque et viverra lacus, vitae ultrices urna. Nunc purus nulla, iaculis at turpis ac, pretium vestibulum odio. Nullam posuere, magna nec ornare interdum, purus sem malesuada lectus, eget mattis lacus turpis et diam. Quisque orci sapien, elementum vitae pretium a, varius vitae ante. Morbi elementum elementum dignissim. Nulla venenatis est et velit pharetra eleifend. Nunc eu eros et augue convallis laoreet feugiat nec purus.\n\n Nunc mi justo, tempus sed aliquet ac, vulputate non sem. Phasellus vel massa aliquam, dapibus neque vitae, convallis odio. Duis in massa bibendum, lacinia arcu vitae, varius enim. Aenean posuere hendrerit neque vel rhoncus. Morbi rutrum nunc vitae fringilla luctus. Phasellus sapien risus, tincidunt in finibus non, mattis ut est. Fusce vehicula efficitur nisi a ultricies. Mauris cursus ut sem vitae fringilla.",
|
||||
"assets": [
|
||||
"https://www.kektus.fr/img/DSC00684.jpg",
|
||||
"https://www.kektus.fr/img/DSC00723.jpg",
|
||||
"https://www.kektus.fr/img/DSC00739.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"date": "2022-07-01T22:20:43.000Z",
|
||||
"location": {
|
||||
"lat": 48.93071193154141,
|
||||
"lon": 2.1544736306563346,
|
||||
"city": "Sartrouville",
|
||||
"country": "France"
|
||||
},
|
||||
"description": "je suis en train de me prendre en photo dans la rue",
|
||||
"assets": [
|
||||
"https://www.kektus.fr/img/DSC09764.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"date": "2023-12-28T23:18:43.511Z",
|
||||
"location": {
|
||||
"lat": 45.8307086344589862,
|
||||
"lon": -1.107245822424634,
|
||||
"city": "Marennes-Hiers-Brouage",
|
||||
"country": "France"
|
||||
},
|
||||
"description": "ce mec est très dangereux",
|
||||
"assets": [
|
||||
"https://www.kektus.fr/img/DSC00671.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"date": "2024-07-21T18:25:43.511Z",
|
||||
"location": {
|
||||
"lat": 45.98963904301394,
|
||||
"lon": -1.3010006132332887,
|
||||
"city": "Saint-Georges-d'Oléron",
|
||||
"country": "France"
|
||||
},
|
||||
"description": "ceci est une **plage** avec un très long texte.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque et viverra lacus, vitae ultrices urna. Nunc purus nulla, iaculis at turpis ac, pretium vestibulum odio. Nullam posuere, magna nec ornare interdum, purus sem malesuada lectus, eget mattis lacus turpis et diam. Quisque orci sapien, elementum vitae pretium a, varius vitae ante. Morbi elementum elementum dignissim. Nulla venenatis est et velit pharetra eleifend. Nunc eu eros et augue convallis laoreet feugiat nec purus.\n\n Nunc mi justo, tempus sed aliquet ac, vulputate non sem. Phasellus vel massa aliquam, dapibus neque vitae, convallis odio. Duis in massa bibendum, lacinia arcu vitae, varius enim. Aenean posuere hendrerit neque vel rhoncus. Morbi rutrum nunc vitae fringilla luctus. Phasellus sapien risus, tincidunt in finibus non, mattis ut est. Fusce vehicula efficitur nisi a ultricies. Mauris cursus ut sem vitae fringilla.",
|
||||
"assets": [
|
||||
"https://www.kektus.fr/img/DSC00684.jpg",
|
||||
"https://www.kektus.fr/img/DSC00723.jpg",
|
||||
"https://www.kektus.fr/img/DSC00739.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"date": "2022-07-01T22:20:43.000Z",
|
||||
"location": {
|
||||
"lat": 48.93071193154141,
|
||||
"lon": 2.1544736306563346,
|
||||
"city": "Sartrouville",
|
||||
"country": "France"
|
||||
},
|
||||
"description": "je suis en train de me prendre en photo dans la rue",
|
||||
"assets": [
|
||||
"https://www.kektus.fr/img/DSC09764.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"date": "2023-12-28T23:18:43.511Z",
|
||||
"location": {
|
||||
"lat": 45.8307086344589862,
|
||||
"lon": -1.107245822424634,
|
||||
"city": "Marennes-Hiers-Brouage",
|
||||
"country": "France"
|
||||
},
|
||||
"description": "ce mec est très dangereux",
|
||||
"assets": [
|
||||
"https://www.kektus.fr/img/DSC00671.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"date": "2024-07-21T18:25:43.511Z",
|
||||
"location": {
|
||||
"lat": 45.98963904301394,
|
||||
"lon": -1.3010006132332887,
|
||||
"city": "Saint-Georges-d'Oléron",
|
||||
"country": "France"
|
||||
},
|
||||
"description": "ceci est une **plage** avec un très long texte.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque et viverra lacus, vitae ultrices urna. Nunc purus nulla, iaculis at turpis ac, pretium vestibulum odio. Nullam posuere, magna nec ornare interdum, purus sem malesuada lectus, eget mattis lacus turpis et diam. Quisque orci sapien, elementum vitae pretium a, varius vitae ante. Morbi elementum elementum dignissim. Nulla venenatis est et velit pharetra eleifend. Nunc eu eros et augue convallis laoreet feugiat nec purus.\n\n Nunc mi justo, tempus sed aliquet ac, vulputate non sem. Phasellus vel massa aliquam, dapibus neque vitae, convallis odio. Duis in massa bibendum, lacinia arcu vitae, varius enim. Aenean posuere hendrerit neque vel rhoncus. Morbi rutrum nunc vitae fringilla luctus. Phasellus sapien risus, tincidunt in finibus non, mattis ut est. Fusce vehicula efficitur nisi a ultricies. Mauris cursus ut sem vitae fringilla.",
|
||||
"assets": [
|
||||
"https://www.kektus.fr/img/DSC00684.jpg",
|
||||
"https://www.kektus.fr/img/DSC00723.jpg",
|
||||
"https://www.kektus.fr/img/DSC00739.jpg"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -9,12 +9,16 @@ const appVersion = ref(import.meta.env.VITE_APP_VERSION)
|
|||
<template>
|
||||
<div class="fixed w-full top-0 z-50 flex items-center backdrop-blur-md bg-black/10 gap-2 px-3">
|
||||
<a href="https://www.kektus.fr"
|
||||
><h1 id="kektus" class="font-bold select-none mx-3 my-3 text-2xl hover:text-3xl transition-all duration-300">
|
||||
kektus</h1></a
|
||||
><h1
|
||||
id="kektus"
|
||||
class="font-bold select-none mx-3 my-3 text-2xl hover:text-3xl transition-all duration-300"
|
||||
>
|
||||
kektus
|
||||
</h1></a
|
||||
>
|
||||
<h1 class="font-light text-lg my-2 mr-3">carnet de voyage été 2024</h1>
|
||||
<div class="flex-grow"></div>
|
||||
<RouterLink :to="{name: 'home'}">
|
||||
<RouterLink :to="{ name: 'home' }">
|
||||
<div class="p-2 bg-black/10 hover:bg-black/20 transition-colors duration-300 rounded-lg">
|
||||
<Images size="20" />
|
||||
</div>
|
||||
|
|
@ -26,8 +30,11 @@ const appVersion = ref(import.meta.env.VITE_APP_VERSION)
|
|||
</RouterLink>
|
||||
</div>
|
||||
<RouterView />
|
||||
<p class="fixed right-0 bottom-0 z-50 p-1 font-extralight text-sm"><a
|
||||
href="https://gitlab.kektus.xyz/kektus/services/summer2024" target="_blank">v{{ appVersion }}</a></p>
|
||||
<p class="fixed right-0 bottom-0 z-50 p-1 font-extralight text-sm">
|
||||
<a href="https://gitlab.kektus.xyz/kektus/services/summer2024" target="_blank"
|
||||
>v{{ appVersion }}</a
|
||||
>
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -2,20 +2,20 @@
|
|||
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap');
|
||||
|
||||
body {
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
}
|
||||
|
||||
#kektus {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
}
|
||||
|
||||
.ol-zoom {
|
||||
top: 120px !important;
|
||||
left: .5em;
|
||||
top: 120px !important;
|
||||
left: 0.5em;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 500px) {
|
||||
.ol-zoom {
|
||||
top: 70px !important;
|
||||
}
|
||||
}
|
||||
.ol-zoom {
|
||||
top: 70px !important;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const countdownInterval = setInterval(() => {
|
|||
const now = new Date().getTime()
|
||||
const distance = countdownDate - now
|
||||
if (distance < 0) {
|
||||
countdownDisplay.value = 'c\'est parti !'
|
||||
countdownDisplay.value = "c'est parti !"
|
||||
clearInterval(countdownInterval)
|
||||
return
|
||||
}
|
||||
|
|
@ -20,18 +20,20 @@ const countdownInterval = setInterval(() => {
|
|||
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60))
|
||||
const seconds = Math.floor((distance % (1000 * 60)) / 1000)
|
||||
|
||||
countdownDisplay.value = `${days} jour` + (days > 1 ? 's' : '') +
|
||||
` ${hours} heure` + (hours > 1 ? 's' : '') +
|
||||
` ${minutes} minute` + (minutes > 1 ? 's' : '') +
|
||||
` ${seconds} seconde` + (seconds > 1 ? 's' : '')
|
||||
countdownDisplay.value =
|
||||
`${days} jour` +
|
||||
(days > 1 ? 's' : '') +
|
||||
` ${hours} heure` +
|
||||
(hours > 1 ? 's' : '') +
|
||||
` ${minutes} minute` +
|
||||
(minutes > 1 ? 's' : '') +
|
||||
` ${seconds} seconde` +
|
||||
(seconds > 1 ? 's' : '')
|
||||
}, 1000)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p :class="props.class">{{ countdownDisplay }}</p>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -14,42 +14,42 @@ const postActionBtn = ref(null)
|
|||
function postDataToggle() {
|
||||
if (postDataVisible.value) {
|
||||
for (const data of postData.value) {
|
||||
data.classList.remove('backdrop-blur-sm');
|
||||
data.classList.remove('bg-gray-400/10');
|
||||
data.classList.add('bg-gray-400/0');
|
||||
data.classList.remove('backdrop-blur-sm')
|
||||
data.classList.remove('bg-gray-400/10')
|
||||
data.classList.add('bg-gray-400/0')
|
||||
}
|
||||
for (const title of postDataTitle.value) {
|
||||
title.classList.add("opacity-0");
|
||||
title.classList.add('opacity-0')
|
||||
}
|
||||
for (const desc of postDataDescription.value) {
|
||||
desc.classList.add("opacity-0");
|
||||
desc.classList.remove("scrollable-element");
|
||||
desc.classList.add('opacity-0')
|
||||
desc.classList.remove('scrollable-element')
|
||||
}
|
||||
for (const btn of postActionBtn.value) {
|
||||
btn.classList.remove("top-0");
|
||||
btn.classList.remove("right-0");
|
||||
btn.classList.add("left-0");
|
||||
btn.classList.add("bottom-0");
|
||||
btn.classList.remove('top-0')
|
||||
btn.classList.remove('right-0')
|
||||
btn.classList.add('left-0')
|
||||
btn.classList.add('bottom-0')
|
||||
}
|
||||
postDataVisible.value = false
|
||||
} else {
|
||||
for (const data of postData.value) {
|
||||
data.classList.add('backdrop-blur-sm');
|
||||
data.classList.add('bg-gray-400/10');
|
||||
data.classList.remove('bg-gray-400/0');
|
||||
data.classList.add('backdrop-blur-sm')
|
||||
data.classList.add('bg-gray-400/10')
|
||||
data.classList.remove('bg-gray-400/0')
|
||||
}
|
||||
for (const title of postDataTitle.value) {
|
||||
title.classList.remove("opacity-0");
|
||||
title.classList.remove('opacity-0')
|
||||
}
|
||||
for (const desc of postDataDescription.value) {
|
||||
desc.classList.remove("opacity-0");
|
||||
desc.classList.add("scrollable-element");
|
||||
desc.classList.remove('opacity-0')
|
||||
desc.classList.add('scrollable-element')
|
||||
}
|
||||
for (const btn of postActionBtn.value) {
|
||||
btn.classList.add("top-0");
|
||||
btn.classList.add("right-0");
|
||||
btn.classList.remove("left-0");
|
||||
btn.classList.remove("bottom-0");
|
||||
btn.classList.add('top-0')
|
||||
btn.classList.add('right-0')
|
||||
btn.classList.remove('left-0')
|
||||
btn.classList.remove('bottom-0')
|
||||
}
|
||||
postDataVisible.value = true
|
||||
}
|
||||
|
|
@ -83,5 +83,4 @@ function postDataToggle() {
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<script setup>
|
||||
import { alertVariants } from ".";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { alertVariants } from '.'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
variant: { type: null, required: false },
|
||||
});
|
||||
variant: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
import { cva } from "class-variance-authority";
|
||||
import { cva } from 'class-variance-authority'
|
||||
|
||||
export { default as Alert } from "./Alert.vue";
|
||||
export { default as AlertTitle } from "./AlertTitle.vue";
|
||||
export { default as AlertDescription } from "./AlertDescription.vue";
|
||||
export { default as Alert } from './Alert.vue'
|
||||
export { default as AlertTitle } from './AlertTitle.vue'
|
||||
export { default as AlertDescription } from './AlertDescription.vue'
|
||||
|
||||
export const alertVariants = cva(
|
||||
"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
|
||||
'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-background text-foreground",
|
||||
default: 'bg-background text-foreground',
|
||||
destructive:
|
||||
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
|
||||
},
|
||||
'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive'
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
variant: 'default'
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,13 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'rounded-lg border bg-card text-card-foreground shadow-sm',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
>
|
||||
<div :class="cn('rounded-lg border bg-card text-card-foreground shadow-sm', props.class)">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h3
|
||||
:class="
|
||||
cn('text-2xl font-semibold leading-none tracking-tight', props.class)
|
||||
"
|
||||
>
|
||||
<h3 :class="cn('text-2xl font-semibold leading-none tracking-tight', props.class)">
|
||||
<slot />
|
||||
</h3>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export { default as Card } from "./Card.vue";
|
||||
export { default as CardHeader } from "./CardHeader.vue";
|
||||
export { default as CardTitle } from "./CardTitle.vue";
|
||||
export { default as CardDescription } from "./CardDescription.vue";
|
||||
export { default as CardContent } from "./CardContent.vue";
|
||||
export { default as CardFooter } from "./CardFooter.vue";
|
||||
export { default as Card } from './Card.vue'
|
||||
export { default as CardHeader } from './CardHeader.vue'
|
||||
export { default as CardTitle } from './CardTitle.vue'
|
||||
export { default as CardDescription } from './CardDescription.vue'
|
||||
export { default as CardContent } from './CardContent.vue'
|
||||
export { default as CardFooter } from './CardFooter.vue'
|
||||
|
|
|
|||
|
|
@ -1,34 +1,34 @@
|
|||
<script setup>
|
||||
import { useProvideCarousel } from "./useCarousel";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useProvideCarousel } from './useCarousel'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
opts: { type: null, required: false },
|
||||
plugins: { type: null, required: false },
|
||||
orientation: { type: String, required: false, default: "horizontal" },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
orientation: { type: String, required: false, default: 'horizontal' },
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const emits = defineEmits(["init-api"]);
|
||||
const emits = defineEmits(['init-api'])
|
||||
|
||||
const carouselArgs = useProvideCarousel(props, emits);
|
||||
const carouselArgs = useProvideCarousel(props, emits)
|
||||
|
||||
defineExpose(carouselArgs);
|
||||
defineExpose(carouselArgs)
|
||||
|
||||
function onKeyDown(event) {
|
||||
const prevKey = props.orientation === "vertical" ? "ArrowUp" : "ArrowLeft";
|
||||
const nextKey = props.orientation === "vertical" ? "ArrowDown" : "ArrowRight";
|
||||
const prevKey = props.orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft'
|
||||
const nextKey = props.orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight'
|
||||
|
||||
if (event.key === prevKey) {
|
||||
event.preventDefault();
|
||||
carouselArgs.scrollPrev();
|
||||
event.preventDefault()
|
||||
carouselArgs.scrollPrev()
|
||||
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
if (event.key === nextKey) {
|
||||
event.preventDefault();
|
||||
carouselArgs.scrollNext();
|
||||
event.preventDefault()
|
||||
carouselArgs.scrollNext()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,28 +1,22 @@
|
|||
<script setup>
|
||||
import { useCarousel } from "./useCarousel";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useCarousel } from './useCarousel'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
});
|
||||
inheritAttrs: false
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const { carouselRef, orientation } = useCarousel();
|
||||
const { carouselRef, orientation } = useCarousel()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="carouselRef" class="overflow-hidden">
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'flex',
|
||||
orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
:class="cn('flex', orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col', props.class)"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<script setup>
|
||||
import { useCarousel } from "./useCarousel";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useCarousel } from './useCarousel'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const { orientation } = useCarousel();
|
||||
const { orientation } = useCarousel()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -17,7 +17,7 @@ const { orientation } = useCarousel();
|
|||
cn(
|
||||
'min-w-0 shrink-0 grow-0 basis-full',
|
||||
orientation === 'horizontal' ? 'pl-4' : 'pt-4',
|
||||
props.class,
|
||||
props.class
|
||||
)
|
||||
"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<script setup>
|
||||
import { ArrowRight } from "lucide-vue-next";
|
||||
import { useCarousel } from "./useCarousel";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ArrowRight } from 'lucide-vue-next'
|
||||
import { useCarousel } from './useCarousel'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const { orientation, canScrollNext, scrollNext } = useCarousel();
|
||||
const { orientation, canScrollNext, scrollNext } = useCarousel()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -20,7 +20,7 @@ const { orientation, canScrollNext, scrollNext } = useCarousel();
|
|||
orientation === 'horizontal'
|
||||
? '-right-12 top-1/2 -translate-y-1/2'
|
||||
: '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',
|
||||
props.class,
|
||||
props.class
|
||||
)
|
||||
"
|
||||
variant="outline"
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<script setup>
|
||||
import { ArrowLeft } from "lucide-vue-next";
|
||||
import { useCarousel } from "./useCarousel";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ArrowLeft } from 'lucide-vue-next'
|
||||
import { useCarousel } from './useCarousel'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const { orientation, canScrollPrev, scrollPrev } = useCarousel();
|
||||
const { orientation, canScrollPrev, scrollPrev } = useCarousel()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -20,7 +20,7 @@ const { orientation, canScrollPrev, scrollPrev } = useCarousel();
|
|||
orientation === 'horizontal'
|
||||
? '-left-12 top-1/2 -translate-y-1/2'
|
||||
: '-top-12 left-1/2 -translate-x-1/2 rotate-90',
|
||||
props.class,
|
||||
props.class
|
||||
)
|
||||
"
|
||||
variant="outline"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export { default as Carousel } from "./Carousel.vue";
|
||||
export { default as CarouselContent } from "./CarouselContent.vue";
|
||||
export { default as CarouselItem } from "./CarouselItem.vue";
|
||||
export { default as CarouselPrevious } from "./CarouselPrevious.vue";
|
||||
export { default as CarouselNext } from "./CarouselNext.vue";
|
||||
export { useCarousel } from "./useCarousel";
|
||||
export { default as Carousel } from './Carousel.vue'
|
||||
export { default as CarouselContent } from './CarouselContent.vue'
|
||||
export { default as CarouselItem } from './CarouselItem.vue'
|
||||
export { default as CarouselPrevious } from './CarouselPrevious.vue'
|
||||
export { default as CarouselNext } from './CarouselNext.vue'
|
||||
export { useCarousel } from './useCarousel'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
export {};
|
||||
export {}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,41 @@
|
|||
import { createInjectionState } from "@vueuse/core";
|
||||
import emblaCarouselVue from "embla-carousel-vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { createInjectionState } from '@vueuse/core'
|
||||
import emblaCarouselVue from 'embla-carousel-vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const [useProvideCarousel, useInjectCarousel] = createInjectionState(
|
||||
({ opts, orientation, plugins }, emits) => {
|
||||
const [emblaNode, emblaApi] = emblaCarouselVue(
|
||||
{
|
||||
...opts,
|
||||
axis: orientation === "horizontal" ? "x" : "y",
|
||||
axis: orientation === 'horizontal' ? 'x' : 'y'
|
||||
},
|
||||
plugins,
|
||||
);
|
||||
plugins
|
||||
)
|
||||
|
||||
function scrollPrev() {
|
||||
emblaApi.value?.scrollPrev();
|
||||
emblaApi.value?.scrollPrev()
|
||||
}
|
||||
function scrollNext() {
|
||||
emblaApi.value?.scrollNext();
|
||||
emblaApi.value?.scrollNext()
|
||||
}
|
||||
|
||||
const canScrollNext = ref(false);
|
||||
const canScrollPrev = ref(false);
|
||||
const canScrollNext = ref(false)
|
||||
const canScrollPrev = ref(false)
|
||||
|
||||
function onSelect(api) {
|
||||
canScrollNext.value = api?.canScrollNext() || false;
|
||||
canScrollPrev.value = api?.canScrollPrev() || false;
|
||||
canScrollNext.value = api?.canScrollNext() || false
|
||||
canScrollPrev.value = api?.canScrollPrev() || false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!emblaApi.value) return;
|
||||
if (!emblaApi.value) return
|
||||
|
||||
emblaApi.value?.on("init", onSelect);
|
||||
emblaApi.value?.on("reInit", onSelect);
|
||||
emblaApi.value?.on("select", onSelect);
|
||||
emblaApi.value?.on('init', onSelect)
|
||||
emblaApi.value?.on('reInit', onSelect)
|
||||
emblaApi.value?.on('select', onSelect)
|
||||
|
||||
emits("init-api", emblaApi.value);
|
||||
});
|
||||
emits('init-api', emblaApi.value)
|
||||
})
|
||||
|
||||
return {
|
||||
carouselRef: emblaNode,
|
||||
|
|
@ -44,18 +44,17 @@ const [useProvideCarousel, useInjectCarousel] = createInjectionState(
|
|||
canScrollNext,
|
||||
scrollPrev,
|
||||
scrollNext,
|
||||
orientation,
|
||||
};
|
||||
},
|
||||
);
|
||||
orientation
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
function useCarousel() {
|
||||
const carouselState = useInjectCarousel();
|
||||
const carouselState = useInjectCarousel()
|
||||
|
||||
if (!carouselState)
|
||||
throw new Error("useCarousel must be used within a <Carousel />");
|
||||
if (!carouselState) throw new Error('useCarousel must be used within a <Carousel />')
|
||||
|
||||
return carouselState;
|
||||
return carouselState
|
||||
}
|
||||
|
||||
export { useCarousel, useProvideCarousel };
|
||||
export { useCarousel, useProvideCarousel }
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
<script setup>
|
||||
import { Slot } from "radix-vue";
|
||||
import { useFormField } from "./useFormField";
|
||||
import { Slot } from 'radix-vue'
|
||||
import { useFormField } from './useFormField'
|
||||
|
||||
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
||||
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Slot
|
||||
:id="formItemId"
|
||||
:aria-describedby="
|
||||
!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`
|
||||
"
|
||||
:aria-describedby="!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`"
|
||||
:aria-invalid="!!error"
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -1,19 +1,16 @@
|
|||
<script setup>
|
||||
import { useFormField } from "./useFormField";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useFormField } from './useFormField'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const { formDescriptionId } = useFormField();
|
||||
const { formDescriptionId } = useFormField()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p
|
||||
:id="formDescriptionId"
|
||||
:class="cn('text-sm text-muted-foreground', props.class)"
|
||||
>
|
||||
<p :id="formDescriptionId" :class="cn('text-sm text-muted-foreground', props.class)">
|
||||
<slot />
|
||||
</p>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<script setup>
|
||||
import { provide } from "vue";
|
||||
import { useId } from "radix-vue";
|
||||
import { FORM_ITEM_INJECTION_KEY } from "./injectionKeys";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { provide } from 'vue'
|
||||
import { useId } from 'radix-vue'
|
||||
import { FORM_ITEM_INJECTION_KEY } from './injectionKeys'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const id = useId();
|
||||
provide(FORM_ITEM_INJECTION_KEY, id);
|
||||
const id = useId()
|
||||
provide(FORM_ITEM_INJECTION_KEY, id)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,20 @@
|
|||
<script setup>
|
||||
import { useFormField } from "./useFormField";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { useFormField } from './useFormField'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Label } from '@/components/ui/label'
|
||||
|
||||
const props = defineProps({
|
||||
for: { type: String, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const { error, formItemId } = useFormField();
|
||||
const { error, formItemId } = useFormField()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Label
|
||||
:class="cn(error && 'text-destructive', props.class)"
|
||||
:for="formItemId"
|
||||
>
|
||||
<Label :class="cn(error && 'text-destructive', props.class)" :for="formItemId">
|
||||
<slot />
|
||||
</Label>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { ErrorMessage } from "vee-validate";
|
||||
import { toValue } from "vue";
|
||||
import { useFormField } from "./useFormField";
|
||||
import { ErrorMessage } from 'vee-validate'
|
||||
import { toValue } from 'vue'
|
||||
import { useFormField } from './useFormField'
|
||||
|
||||
const { name, formMessageId } = useFormField();
|
||||
const { name, formMessageId } = useFormField()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export { Form, Field as FormField } from "vee-validate";
|
||||
export { default as FormItem } from "./FormItem.vue";
|
||||
export { default as FormLabel } from "./FormLabel.vue";
|
||||
export { default as FormControl } from "./FormControl.vue";
|
||||
export { default as FormMessage } from "./FormMessage.vue";
|
||||
export { default as FormDescription } from "./FormDescription.vue";
|
||||
export { FORM_ITEM_INJECTION_KEY } from "./injectionKeys";
|
||||
export { Form, Field as FormField } from 'vee-validate'
|
||||
export { default as FormItem } from './FormItem.vue'
|
||||
export { default as FormLabel } from './FormLabel.vue'
|
||||
export { default as FormControl } from './FormControl.vue'
|
||||
export { default as FormMessage } from './FormMessage.vue'
|
||||
export { default as FormDescription } from './FormDescription.vue'
|
||||
export { FORM_ITEM_INJECTION_KEY } from './injectionKeys'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
export const FORM_ITEM_INJECTION_KEY = Symbol();
|
||||
export const FORM_ITEM_INJECTION_KEY = Symbol()
|
||||
|
|
|
|||
|
|
@ -3,27 +3,26 @@ import {
|
|||
useFieldError,
|
||||
useIsFieldDirty,
|
||||
useIsFieldTouched,
|
||||
useIsFieldValid,
|
||||
} from "vee-validate";
|
||||
import { inject } from "vue";
|
||||
import { FORM_ITEM_INJECTION_KEY } from "./injectionKeys";
|
||||
useIsFieldValid
|
||||
} from 'vee-validate'
|
||||
import { inject } from 'vue'
|
||||
import { FORM_ITEM_INJECTION_KEY } from './injectionKeys'
|
||||
|
||||
export function useFormField() {
|
||||
const fieldContext = inject(FieldContextKey);
|
||||
const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY);
|
||||
const fieldContext = inject(FieldContextKey)
|
||||
const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY)
|
||||
|
||||
if (!fieldContext)
|
||||
throw new Error("useFormField should be used within <FormField>");
|
||||
if (!fieldContext) throw new Error('useFormField should be used within <FormField>')
|
||||
|
||||
const { name } = fieldContext;
|
||||
const id = fieldItemContext;
|
||||
const { name } = fieldContext
|
||||
const id = fieldItemContext
|
||||
|
||||
const fieldState = {
|
||||
valid: useIsFieldValid(name),
|
||||
isDirty: useIsFieldDirty(name),
|
||||
isTouched: useIsFieldTouched(name),
|
||||
error: useFieldError(name),
|
||||
};
|
||||
error: useFieldError(name)
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
|
|
@ -31,6 +30,6 @@ export function useFormField() {
|
|||
formItemId: `${id}-form-item`,
|
||||
formDescriptionId: `${id}-form-item-description`,
|
||||
formMessageId: `${id}-form-item-message`,
|
||||
...fieldState,
|
||||
};
|
||||
...fieldState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
<script setup>
|
||||
import { useVModel } from "@vueuse/core";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
defaultValue: { type: [String, Number], required: false },
|
||||
modelValue: { type: [String, Number], required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const emits = defineEmits(['update:modelValue'])
|
||||
|
||||
const modelValue = useVModel(props, "modelValue", emits, {
|
||||
const modelValue = useVModel(props, 'modelValue', emits, {
|
||||
passive: true,
|
||||
defaultValue: props.defaultValue,
|
||||
});
|
||||
defaultValue: props.defaultValue
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -22,7 +22,7 @@ const modelValue = useVModel(props, "modelValue", emits, {
|
|||
:class="
|
||||
cn(
|
||||
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
props.class,
|
||||
props.class
|
||||
)
|
||||
"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
export { default as Input } from "./Input.vue";
|
||||
export { default as Input } from './Input.vue'
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { Label } from "radix-vue";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { computed } from 'vue'
|
||||
import { Label } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
for: { type: String, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props;
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated;
|
||||
});
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -23,7 +23,7 @@ const delegatedProps = computed(() => {
|
|||
:class="
|
||||
cn(
|
||||
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
||||
props.class,
|
||||
props.class
|
||||
)
|
||||
"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
export { default as Label } from "./Label.vue";
|
||||
export { default as Label } from './Label.vue'
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<td
|
||||
:class="cn('p-4 align-middle [&:has([role=checkbox])]:pr-0', props.class)"
|
||||
>
|
||||
<td :class="cn('p-4 align-middle [&:has([role=checkbox])]:pr-0', props.class)">
|
||||
<slot />
|
||||
</td>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,29 +1,25 @@
|
|||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import TableRow from "./TableRow.vue";
|
||||
import TableCell from "./TableCell.vue";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { computed } from 'vue'
|
||||
import TableRow from './TableRow.vue'
|
||||
import TableCell from './TableCell.vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
colspan: { type: Number, required: false, default: 1 },
|
||||
});
|
||||
colspan: { type: Number, required: false, default: 1 }
|
||||
})
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props;
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated;
|
||||
});
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableRow>
|
||||
<TableCell
|
||||
:class="
|
||||
cn(
|
||||
'p-4 whitespace-nowrap align-middle text-sm text-foreground',
|
||||
props.class
|
||||
)"
|
||||
:class="cn('p-4 whitespace-nowrap align-middle text-sm text-foreground', props.class)"
|
||||
v-bind="delegatedProps"
|
||||
>
|
||||
<div class="flex items-center justify-center py-10">
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<tfoot
|
||||
:class="
|
||||
cn('border-t bg-muted/50 font-medium [&>tr]:last:border-b-0', props.class)
|
||||
"
|
||||
>
|
||||
<tfoot :class="cn('border-t bg-muted/50 font-medium [&>tr]:last:border-b-0', props.class)">
|
||||
<slot />
|
||||
</tfoot>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -11,7 +11,7 @@ const props = defineProps({
|
|||
:class="
|
||||
cn(
|
||||
'h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0',
|
||||
props.class,
|
||||
props.class
|
||||
)
|
||||
"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,15 @@
|
|||
<script setup>
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<tr
|
||||
:class="
|
||||
cn(
|
||||
'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
|
||||
props.class,
|
||||
)
|
||||
cn('border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted', props.class)
|
||||
"
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
export { default as Table } from "./Table.vue";
|
||||
export { default as TableBody } from "./TableBody.vue";
|
||||
export { default as TableCell } from "./TableCell.vue";
|
||||
export { default as TableHead } from "./TableHead.vue";
|
||||
export { default as TableHeader } from "./TableHeader.vue";
|
||||
export { default as TableFooter } from "./TableFooter.vue";
|
||||
export { default as TableRow } from "./TableRow.vue";
|
||||
export { default as TableCaption } from "./TableCaption.vue";
|
||||
export { default as TableEmpty } from "./TableEmpty.vue";
|
||||
export { default as Table } from './Table.vue'
|
||||
export { default as TableBody } from './TableBody.vue'
|
||||
export { default as TableCell } from './TableCell.vue'
|
||||
export { default as TableHead } from './TableHead.vue'
|
||||
export { default as TableHeader } from './TableHeader.vue'
|
||||
export { default as TableFooter } from './TableFooter.vue'
|
||||
export { default as TableRow } from './TableRow.vue'
|
||||
export { default as TableCaption } from './TableCaption.vue'
|
||||
export { default as TableEmpty } from './TableEmpty.vue'
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
<script setup>
|
||||
import { useVModel } from "@vueuse/core";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: { type: null, required: false },
|
||||
defaultValue: { type: [String, Number], required: false },
|
||||
modelValue: { type: [String, Number], required: false },
|
||||
});
|
||||
modelValue: { type: [String, Number], required: false }
|
||||
})
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const emits = defineEmits(['update:modelValue'])
|
||||
|
||||
const modelValue = useVModel(props, "modelValue", emits, {
|
||||
const modelValue = useVModel(props, 'modelValue', emits, {
|
||||
passive: true,
|
||||
defaultValue: props.defaultValue,
|
||||
});
|
||||
defaultValue: props.defaultValue
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -22,7 +22,7 @@ const modelValue = useVModel(props, "modelValue", emits, {
|
|||
:class="
|
||||
cn(
|
||||
'flex min-h-20 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
props.class,
|
||||
props.class
|
||||
)
|
||||
"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
export { default as Textarea } from "./Textarea.vue";
|
||||
export { default as Textarea } from './Textarea.vue'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { TooltipRoot, useForwardPropsEmits } from "radix-vue";
|
||||
import { TooltipRoot, useForwardPropsEmits } from 'radix-vue'
|
||||
|
||||
const props = defineProps({
|
||||
defaultOpen: { type: Boolean, required: false },
|
||||
|
|
@ -8,11 +8,11 @@ const props = defineProps({
|
|||
disableHoverableContent: { type: Boolean, required: false },
|
||||
disableClosingTrigger: { type: Boolean, required: false },
|
||||
disabled: { type: Boolean, required: false },
|
||||
ignoreNonKeyboardFocus: { type: Boolean, required: false },
|
||||
});
|
||||
const emits = defineEmits(["update:open"]);
|
||||
ignoreNonKeyboardFocus: { type: Boolean, required: false }
|
||||
})
|
||||
const emits = defineEmits(['update:open'])
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits);
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { TooltipContent, TooltipPortal, useForwardPropsEmits } from "radix-vue";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { computed } from 'vue'
|
||||
import { TooltipContent, TooltipPortal, useForwardPropsEmits } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
});
|
||||
inheritAttrs: false
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
forceMount: { type: Boolean, required: false },
|
||||
|
|
@ -22,18 +22,18 @@ const props = defineProps({
|
|||
arrowPadding: { type: Number, required: false },
|
||||
sticky: { type: String, required: false },
|
||||
hideWhenDetached: { type: Boolean, required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
class: { type: null, required: false }
|
||||
})
|
||||
|
||||
const emits = defineEmits(["escapeKeyDown", "pointerDownOutside"]);
|
||||
const emits = defineEmits(['escapeKeyDown', 'pointerDownOutside'])
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props;
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated;
|
||||
});
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -43,7 +43,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
|||
:class="
|
||||
cn(
|
||||
'z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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,
|
||||
props.class
|
||||
)
|
||||
"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { TooltipProvider } from "radix-vue";
|
||||
import { TooltipProvider } from 'radix-vue'
|
||||
|
||||
const props = defineProps({
|
||||
delayDuration: { type: Number, required: false },
|
||||
|
|
@ -7,8 +7,8 @@ const props = defineProps({
|
|||
disableHoverableContent: { type: Boolean, required: false },
|
||||
disableClosingTrigger: { type: Boolean, required: false },
|
||||
disabled: { type: Boolean, required: false },
|
||||
ignoreNonKeyboardFocus: { type: Boolean, required: false },
|
||||
});
|
||||
ignoreNonKeyboardFocus: { type: Boolean, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<script setup>
|
||||
import { TooltipTrigger } from "radix-vue";
|
||||
import { TooltipTrigger } from 'radix-vue'
|
||||
|
||||
const props = defineProps({
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
});
|
||||
as: { type: null, required: false }
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export { default as Tooltip } from "./Tooltip.vue";
|
||||
export { default as TooltipContent } from "./TooltipContent.vue";
|
||||
export { default as TooltipTrigger } from "./TooltipTrigger.vue";
|
||||
export { default as TooltipProvider } from "./TooltipProvider.vue";
|
||||
export { default as Tooltip } from './Tooltip.vue'
|
||||
export { default as TooltipContent } from './TooltipContent.vue'
|
||||
export { default as TooltipTrigger } from './TooltipTrigger.vue'
|
||||
export { default as TooltipProvider } from './TooltipProvider.vue'
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@ import VueFullPage from 'vue-fullpage.js'
|
|||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
import "vue3-openlayers/styles.css";
|
||||
import OpenLayersMap from "vue3-openlayers";
|
||||
import 'vue3-openlayers/styles.css'
|
||||
import OpenLayersMap from 'vue3-openlayers'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(VueFullPage)
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
app.use(OpenLayersMap);
|
||||
app.use(OpenLayersMap)
|
||||
|
||||
app.mount('#app')
|
||||
|
|
|
|||
|
|
@ -2,41 +2,39 @@ import { defineStore } from 'pinia'
|
|||
import { ref } from 'vue'
|
||||
import { API_BASE_URL } from '@/config.js'
|
||||
|
||||
export const useAuthStore = defineStore("auth", () => {
|
||||
const adminToken = ref("");
|
||||
const isAuth = ref(false);
|
||||
const error = ref(false);
|
||||
export const useAuthStore = defineStore('auth', () => {
|
||||
const adminToken = ref('')
|
||||
const isAuth = ref(false)
|
||||
const error = ref(false)
|
||||
|
||||
function login(token) {
|
||||
adminToken.value = "";
|
||||
isAuth.value = false;
|
||||
error.value = false;
|
||||
adminToken.value = ''
|
||||
isAuth.value = false
|
||||
error.value = false
|
||||
|
||||
return fetch(API_BASE_URL + "/admin/auth/check", {
|
||||
return fetch(API_BASE_URL + '/admin/auth/check', {
|
||||
headers: {
|
||||
"X-admin-token": token
|
||||
'X-admin-token': token
|
||||
}
|
||||
}).then(resp => {
|
||||
}).then((resp) => {
|
||||
if (resp.ok) {
|
||||
adminToken.value = token;
|
||||
isAuth.value = true;
|
||||
localStorage.setItem("kektus-summer-admin-token", token)
|
||||
adminToken.value = token
|
||||
isAuth.value = true
|
||||
localStorage.setItem('kektus-summer-admin-token', token)
|
||||
} else {
|
||||
error.value = true;
|
||||
error.value = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function checkFromLocalStorage() {
|
||||
const storedToken = localStorage.getItem("kektus-summer-admin-token")
|
||||
const storedToken = localStorage.getItem('kektus-summer-admin-token')
|
||||
if (storedToken) {
|
||||
return login(storedToken)
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
|
||||
|
||||
return { adminToken, login, checkFromLocalStorage, isAuth, error }
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<script setup>
|
||||
|
||||
import { Button } from '@/components/ui/button/index.js'
|
||||
import { CirclePlus, Pencil, Trash, MapPin } from 'lucide-vue-next'
|
||||
import { useAdminPostsStore } from '@/stores/adminPosts.js'
|
||||
|
|
@ -72,6 +71,4 @@ onMounted(() => {
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,14 @@ import { Label } from '@/components/ui/label/index.js'
|
|||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { z } from 'zod'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { AlertCircle, ArrowLeft, ArrowRight, CircleCheckBig, CirclePlus, RefreshCcw } from 'lucide-vue-next'
|
||||
import {
|
||||
AlertCircle,
|
||||
ArrowLeft,
|
||||
ArrowRight,
|
||||
CircleCheckBig,
|
||||
CirclePlus,
|
||||
RefreshCcw
|
||||
} from 'lucide-vue-next'
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<script setup>
|
||||
|
||||
import { useAuthStore } from '@/stores/auth.js'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { z } from 'zod'
|
||||
|
|
@ -14,15 +13,17 @@ import router from '@/router/index.js'
|
|||
import { useRoute } from 'vue-router'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const nextView = useRoute().query.redirect;
|
||||
const nextView = useRoute().query.redirect
|
||||
|
||||
onMounted(() => {
|
||||
authStore.checkFromLocalStorage().then(onLogin);
|
||||
authStore.checkFromLocalStorage().then(onLogin)
|
||||
})
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
token: z.string().min(1)
|
||||
}))
|
||||
const formSchema = toTypedSchema(
|
||||
z.object({
|
||||
token: z.string().min(1)
|
||||
})
|
||||
)
|
||||
const form = useForm({
|
||||
validationSchema: formSchema
|
||||
})
|
||||
|
|
@ -32,16 +33,14 @@ const onSubmit = form.handleSubmit((values) => {
|
|||
})
|
||||
|
||||
function onLogin() {
|
||||
if (!authStore.isAuth)
|
||||
return;
|
||||
if (!authStore.isAuth) return
|
||||
|
||||
if (nextView) {
|
||||
router.push(nextView);
|
||||
router.push(nextView)
|
||||
} else {
|
||||
router.push({name: "admin"});
|
||||
router.push({ name: 'admin' })
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -57,7 +56,6 @@ function onLogin() {
|
|||
<AlertDescription>Token invalide</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
|
||||
<div id="form-container" ref="formContainer">
|
||||
<form id="login-form" class="space-y-6" @submit="onSubmit">
|
||||
<FormField v-slot="{ componentField }" name="token">
|
||||
|
|
@ -68,15 +66,11 @@ function onLogin() {
|
|||
</FormControl>
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<Button class="mt-6 w-full" type="submit">
|
||||
Login
|
||||
</Button>
|
||||
<Button class="mt-6 w-full" type="submit"> Login </Button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
<script setup>
|
||||
|
||||
import { usePostsStore } from '@/stores/posts.js'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { Camera, Goal, MapPin } from 'lucide-vue-next'
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip/index.js'
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger
|
||||
} from '@/components/ui/tooltip/index.js'
|
||||
import { useLocationStore } from '@/stores/location.js'
|
||||
import { fromLonLat } from 'ol/proj.js'
|
||||
|
||||
|
|
@ -39,16 +43,8 @@ const goalLocations = ref([
|
|||
|
||||
<template>
|
||||
<div class="fixed h-full w-full">
|
||||
<ol-map
|
||||
:loadTilesWhileAnimating="true"
|
||||
:loadTilesWhileInteracting="true"
|
||||
class="h-full w-full"
|
||||
>
|
||||
<ol-view
|
||||
ref="view"
|
||||
:zoom="3.6"
|
||||
:center="[ 652293.6169027708, 6425265.202945196 ]"
|
||||
/>
|
||||
<ol-map :loadTilesWhileAnimating="true" :loadTilesWhileInteracting="true" class="h-full w-full">
|
||||
<ol-view ref="view" :zoom="3.6" :center="[652293.6169027708, 6425265.202945196]" />
|
||||
|
||||
<ol-tile-layer>
|
||||
<ol-source-osm />
|
||||
|
|
@ -56,16 +52,18 @@ const goalLocations = ref([
|
|||
<ol-scaleline-control />
|
||||
|
||||
<ol-overlay
|
||||
v-for="post in postStore.posts" :key="post.id"
|
||||
v-for="post in postStore.posts"
|
||||
:key="post.id"
|
||||
:position="post.projectedCoordinates"
|
||||
:autoPan="true"
|
||||
>
|
||||
<TooltipProvider>
|
||||
<Tooltip :default-open="true">
|
||||
<TooltipTrigger as-child>
|
||||
<RouterLink :to="{ name: 'home', hash: '#post-' + post.id}">
|
||||
<RouterLink :to="{ name: 'home', hash: '#post-' + post.id }">
|
||||
<div
|
||||
class="-translate-x-1/2 -translate-y-1/2 p-1 rounded-lg bg-indigo-950 hover:bg-indigo-900 transition-colors duration-200">
|
||||
class="-translate-x-1/2 -translate-y-1/2 p-1 rounded-lg bg-indigo-950 hover:bg-indigo-900 transition-colors duration-200"
|
||||
>
|
||||
<Camera size="16" />
|
||||
</div>
|
||||
</RouterLink>
|
||||
|
|
@ -85,7 +83,8 @@ const goalLocations = ref([
|
|||
<Tooltip :default-open="true">
|
||||
<TooltipTrigger as-child>
|
||||
<div
|
||||
class="-translate-x-1/2 -translate-y-1/2 p-1 rounded-lg bg-rose-950 hover:bg-rose-900 transition-colors duration-200">
|
||||
class="-translate-x-1/2 -translate-y-1/2 p-1 rounded-lg bg-rose-950 hover:bg-rose-900 transition-colors duration-200"
|
||||
>
|
||||
<MapPin size="16" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
|
|
@ -97,7 +96,8 @@ const goalLocations = ref([
|
|||
</ol-overlay>
|
||||
|
||||
<ol-overlay
|
||||
v-for="loc in goalLocations" :key="loc.name"
|
||||
v-for="loc in goalLocations"
|
||||
:key="loc.name"
|
||||
:position="loc.coords"
|
||||
:autoPan="true"
|
||||
>
|
||||
|
|
@ -105,7 +105,8 @@ const goalLocations = ref([
|
|||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<div
|
||||
class="-translate-x-1/2 -translate-y-1/2 p-1 rounded-lg bg-emerald-800 hover:bg-emerald-700 transition-colors duration-200">
|
||||
class="-translate-x-1/2 -translate-y-1/2 p-1 rounded-lg bg-emerald-800 hover:bg-emerald-700 transition-colors duration-200"
|
||||
>
|
||||
<Goal size="16" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
|
|
@ -119,15 +120,9 @@ const goalLocations = ref([
|
|||
<ol-vector-layer v-if="postsLinesCoordinates.length > 1">
|
||||
<ol-source-vector>
|
||||
<ol-feature ref="profileFeatureRef">
|
||||
<ol-geom-line-string
|
||||
:coordinates="postsLinesCoordinates"
|
||||
></ol-geom-line-string>
|
||||
<ol-geom-line-string :coordinates="postsLinesCoordinates"></ol-geom-line-string>
|
||||
<ol-style>
|
||||
<ol-style-stroke
|
||||
color="white"
|
||||
width="5"
|
||||
:lineDash="[15, 15]"
|
||||
></ol-style-stroke>
|
||||
<ol-style-stroke color="white" width="5" :lineDash="[15, 15]"></ol-style-stroke>
|
||||
</ol-style>
|
||||
</ol-feature>
|
||||
</ol-source-vector>
|
||||
|
|
@ -136,5 +131,4 @@ const goalLocations = ref([
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ instance it still finds a way to be alive and break when changing views????
|
|||
*/
|
||||
|
||||
async function initFullpage() {
|
||||
if (fullPageInit)
|
||||
return
|
||||
if (fullPageInit) return
|
||||
|
||||
fullpageKey.value += 5
|
||||
fullpageEnable.value = true
|
||||
|
|
@ -41,7 +40,9 @@ async function initFullpage() {
|
|||
try {
|
||||
fullpage.value.init()
|
||||
} catch (e) {
|
||||
console.log('failed to reload fullpage.js because it sucks with vue, reloading page as last resort')
|
||||
console.log(
|
||||
'failed to reload fullpage.js because it sucks with vue, reloading page as last resort'
|
||||
)
|
||||
window.location.reload()
|
||||
return
|
||||
}
|
||||
|
|
@ -57,7 +58,10 @@ onMounted(() => {
|
|||
|
||||
onBeforeUnmount(async () => {
|
||||
console.log('caught post view unmount')
|
||||
if (typeof window.fullpage_api !== 'undefined' && typeof window.fullpage_api.destroy !== 'undefined') {
|
||||
if (
|
||||
typeof window.fullpage_api !== 'undefined' &&
|
||||
typeof window.fullpage_api.destroy !== 'undefined'
|
||||
) {
|
||||
window.fullpage_api.destroy('all')
|
||||
}
|
||||
fullpageKey.value++
|
||||
|
|
@ -100,11 +104,18 @@ function onLeave(origin, destination, direction, trigger) {
|
|||
class="col-start-1 col-span-full row-start-1 max-h-52 h-fit mt-28 sm:mt-16 lg:m-0 lg:col-start-5 lg:col-span-1 lg:row-start-3 lg:row-span-1 pointer-events-auto overflow-y-scroll transition-opacity duration-1000 opacity-0"
|
||||
ref="menu"
|
||||
>
|
||||
<li :data-menuanchor="'post-' + post.id" v-for="post in postsStore.posts" :key="post.id"
|
||||
class="m-2 backdrop-blur-sm rounded-lg bg-black/10 hover:bg-gray-500/10 transition-colors duration-200"
|
||||
ref="menuItems">
|
||||
<a :href="'#post-' + post.id"
|
||||
class="block text-right px-4 py-3 transition-all duration-300">{{ post.formatedDate }}</a>
|
||||
<li
|
||||
:data-menuanchor="'post-' + post.id"
|
||||
v-for="post in postsStore.posts"
|
||||
:key="post.id"
|
||||
class="m-2 backdrop-blur-sm rounded-lg bg-black/10 hover:bg-gray-500/10 transition-colors duration-200"
|
||||
ref="menuItems"
|
||||
>
|
||||
<a
|
||||
:href="'#post-' + post.id"
|
||||
class="block text-right px-4 py-3 transition-all duration-300"
|
||||
>{{ post.formatedDate }}</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -123,7 +134,6 @@ function onLeave(origin, destination, direction, trigger) {
|
|||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
#menu li.active,
|
||||
#menu li.active:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
|
|
|
|||
|
|
@ -13,10 +13,12 @@ import { API_BASE_URL } from '@/config.js'
|
|||
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
latitude: z.number(),
|
||||
longitude: z.number()
|
||||
}))
|
||||
const formSchema = toTypedSchema(
|
||||
z.object({
|
||||
latitude: z.number(),
|
||||
longitude: z.number()
|
||||
})
|
||||
)
|
||||
const form = useForm({
|
||||
validationSchema: formSchema
|
||||
})
|
||||
|
|
@ -33,8 +35,7 @@ const formStatus = ref({
|
|||
})
|
||||
|
||||
const onSubmit = form.handleSubmit(async (values) => {
|
||||
if (!authStore.isAuth)
|
||||
return
|
||||
if (!authStore.isAuth) return
|
||||
|
||||
console.log('Envoi de la localisation...')
|
||||
formContainer.value.classList.add('hidden')
|
||||
|
|
@ -55,7 +56,8 @@ const onSubmit = form.handleSubmit(async (values) => {
|
|||
console.log('POST post API failed: ' + response.statusText + '\n\n' + response.body)
|
||||
formStatus.value.sending = false
|
||||
formStatus.value.error = true
|
||||
formStatus.value.errorMsg = 'Une erreur est survenue lors de l\'envoi du poste : ' + response.statusText
|
||||
formStatus.value.errorMsg =
|
||||
"Une erreur est survenue lors de l'envoi du poste : " + response.statusText
|
||||
formContainer.value.classList.remove('hidden')
|
||||
return
|
||||
}
|
||||
|
|
@ -79,7 +81,6 @@ onUnmounted(() => {
|
|||
navigator.geolocation.clearWatch(geoWatchId)
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -133,5 +134,4 @@ onUnmounted(() => {
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue