Compare commits
5 Commits
v0.1.11
...
ab563a7b37
| Author | SHA1 | Date | |
|---|---|---|---|
| ab563a7b37 | |||
| 2cfc1a0047 | |||
| 98e8d971e8 | |||
| 87be06ecea | |||
| 28f6e1ae7c |
@@ -1,9 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { fr } from "@nuxt/ui/locale";
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<UApp :locale="fr">
|
||||||
<NuxtRouteAnnouncer />
|
<NuxtRouteAnnouncer />
|
||||||
<NuxtLoadingIndicator />
|
<NuxtLoadingIndicator />
|
||||||
<NuxtLayout>
|
<NuxtLayout>
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
</NuxtLayout>
|
</NuxtLayout>
|
||||||
</div>
|
</UApp>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import type { ButtonProps } from "@nuxt/ui";
|
|||||||
|
|
||||||
type AcfLinkButtonProps = & Omit<ButtonProps, "to" | "target" | "href"> & {
|
type AcfLinkButtonProps = & Omit<ButtonProps, "to" | "target" | "href"> & {
|
||||||
link?: AcfLinkFragment;
|
link?: AcfLinkFragment;
|
||||||
|
showLabel?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const { link, ...buttonProps } = defineProps<AcfLinkButtonProps>();
|
const { link, showLabel, ...buttonProps } = defineProps<AcfLinkButtonProps>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -18,6 +19,6 @@ const { link, ...buttonProps } = defineProps<AcfLinkButtonProps>();
|
|||||||
:external="link.target === '_blank'"
|
:external="link.target === '_blank'"
|
||||||
:rel="link.target === '_blank' ? 'noopener noreferrer' : undefined"
|
:rel="link.target === '_blank' ? 'noopener noreferrer' : undefined"
|
||||||
>
|
>
|
||||||
<slot>{{ link.title }}</slot>
|
<slot>{{ showLabel ? link.title : "" }}</slot>
|
||||||
</UButton>
|
</UButton>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
fragment AcfMedia on GroupAbstractMedia_Fields {
|
fragment AcfMedia on GroupAbstractMedia_Fields {
|
||||||
image {
|
image { node { ... AcfImage } }
|
||||||
node {
|
|
||||||
...AcfImage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aspectRatio
|
aspectRatio
|
||||||
objectFit
|
objectFit
|
||||||
}
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
const { isLoggedIn } = useAuth();
|
|
||||||
const attrs = computed(() => {
|
|
||||||
return isLoggedIn.value
|
|
||||||
? {
|
|
||||||
label: "Déconnexion",
|
|
||||||
icon: "i-lucide-log-out",
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
label: "Connexion",
|
|
||||||
icon: "i-lucide-log-in",
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<AuthState>
|
|
||||||
<UButton to="/connexion" v-bind="attrs" color="neutral" />
|
|
||||||
</AuthState>
|
|
||||||
</template>
|
|
||||||
@@ -34,7 +34,7 @@ const classes = tvSectionHeroSplit({
|
|||||||
<section :class="classes.base()">
|
<section :class="classes.base()">
|
||||||
<div :class="classes.container()">
|
<div :class="classes.container()">
|
||||||
<UiProse :content="content" :class="classes.content()" />
|
<UiProse :content="content" :class="classes.content()" />
|
||||||
<AcfMedia :media="$props" :class="classes.media()" />
|
<AcfMedia :media="parseAcfMedia(props)" :class="classes.media()" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const { connexionButton } = useAuthConnexion();
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="bg-inverted text-inverted py-1.5">
|
<div class="bg-inverted text-inverted py-1.5">
|
||||||
<div class="container flex flex-col sm:flex-row items-center gap-3">
|
<div class="container flex flex-col sm:flex-row items-center gap-3">
|
||||||
<SiteFooterCopyright class="sm:mr-auto" />
|
<SiteFooterCopyright class="sm:mr-auto" />
|
||||||
<AuthConnexionButton color="neutral" variant="link" />
|
<UButton v-bind="connexionButton" color="neutral" variant="link" />
|
||||||
<SiteFooterCredits />
|
<SiteFooterCredits />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,8 +8,5 @@
|
|||||||
<SvgSiteLogo class="h-12 w-auto" />
|
<SvgSiteLogo class="h-12 w-auto" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
|
||||||
<AuthConnexionButton />
|
|
||||||
</template>
|
|
||||||
</UHeader>
|
</UHeader>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -2,5 +2,6 @@ export function useAuth() {
|
|||||||
const { loggedIn: isLoggedIn, session } = useUserSession();
|
const { loggedIn: isLoggedIn, session } = useUserSession();
|
||||||
const hasRole = (role: string) => session.value?.user?.roles?.includes(role) || false;
|
const hasRole = (role: string) => session.value?.user?.roles?.includes(role) || false;
|
||||||
const isAdmin = computed(() => hasRole("administrator"));
|
const isAdmin = computed(() => hasRole("administrator"));
|
||||||
|
|
||||||
return { isLoggedIn, hasRole, isAdmin };
|
return { isLoggedIn, hasRole, isAdmin };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { FormSubmitEvent } from "@nuxt/ui";
|
|||||||
const isRedirecting = ref(false);
|
const isRedirecting = ref(false);
|
||||||
|
|
||||||
export function useAuthConnexion() {
|
export function useAuthConnexion() {
|
||||||
|
const { isLoggedIn } = useAuth();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { fetch: refreshUserSession } = useUserSession();
|
const { fetch: refreshUserSession } = useUserSession();
|
||||||
const routeRedirect = useRoute().query.redirect as string || undefined;
|
const routeRedirect = useRoute().query.redirect as string || undefined;
|
||||||
@@ -67,5 +68,12 @@ export function useAuthConnexion() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { isRedirecting, login, logout };
|
// Dynamic connexion link
|
||||||
|
const connexionButton = computed(() => ({
|
||||||
|
label: isLoggedIn.value ? "Déconnexion" : "Connexion",
|
||||||
|
icon: isLoggedIn.value ? "i-lucide-log-out" : "i-lucide-log-in",
|
||||||
|
to: "/connexion",
|
||||||
|
}));
|
||||||
|
|
||||||
|
return { isRedirecting, login, logout, connexionButton };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { fr } from "@nuxt/ui/locale";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UApp id="layout-default" :locale="fr">
|
<div id="layout-default">
|
||||||
<SiteHeader />
|
<SiteHeader />
|
||||||
<UMain>
|
<UMain>
|
||||||
<slot />
|
<slot />
|
||||||
</UMain>
|
</UMain>
|
||||||
<SiteFooter />
|
<SiteFooter />
|
||||||
</UApp>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
18
wp-content/themes/moonshine/app/utils/acf-link.ts
Normal file
18
wp-content/themes/moonshine/app/utils/acf-link.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import * as z from "zod";
|
||||||
|
import type { AcfLinkFragment } from "#graphql/operations";
|
||||||
|
|
||||||
|
const acfLinkSchema = z.object({
|
||||||
|
title: z.string(),
|
||||||
|
url: z.string(),
|
||||||
|
target: z.string().optional().default(""),
|
||||||
|
});
|
||||||
|
export type AcfLinkOutput = z.infer<typeof acfLinkSchema>;
|
||||||
|
|
||||||
|
export function parseAcfLink(data?: Partial<AcfLinkFragment>) {
|
||||||
|
try {
|
||||||
|
return acfLinkSchema.parse(data);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
wp-content/themes/moonshine/app/utils/acf-media.ts
Normal file
29
wp-content/themes/moonshine/app/utils/acf-media.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import type { AcfMediaFragment } from "#graphql/operations";
|
||||||
|
import * as z from "zod";
|
||||||
|
|
||||||
|
export const acfImageSchema = z.object({
|
||||||
|
src: z.url(),
|
||||||
|
alt: z.string(),
|
||||||
|
mediaDetails: z.object({
|
||||||
|
width: z.number(),
|
||||||
|
height: z.number(),
|
||||||
|
}),
|
||||||
|
objectPosition: z.string().optional().default("center"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const acfMediaSchema = z.object({
|
||||||
|
image: z.object({
|
||||||
|
node: acfImageSchema,
|
||||||
|
}),
|
||||||
|
aspectRatio: z.enum(["square", "video", "portrait", "auto"]).optional().default("auto"),
|
||||||
|
objectFit: z.enum(["cover", "contain"]).optional().default("cover"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export function parseAcfMedia(data?: Partial<AcfMediaFragment>) {
|
||||||
|
try {
|
||||||
|
return acfMediaSchema.parse(data);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -119,4 +119,5 @@ export default defineNuxtConfig({
|
|||||||
componentPrefix: "Svg",
|
componentPrefix: "Svg",
|
||||||
defaultImport: "component",
|
defaultImport: "component",
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user