initial commit
This commit is contained in:
64
app/components/button/base.vue
Normal file
64
app/components/button/base.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<button
|
||||
:disabled="disabled"
|
||||
:class="variantClass"
|
||||
@click="$emit('click')"
|
||||
>
|
||||
<slot v-if="!loading"></slot>
|
||||
<slot name="spinner" v-else>
|
||||
<UiSpinnerCpnt />
|
||||
</slot>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineEmits(['click'])
|
||||
|
||||
const props = defineProps<{
|
||||
disabled?: boolean
|
||||
loading?: boolean
|
||||
variant?: 'primary' | 'secondary'
|
||||
}>()
|
||||
|
||||
const variantClass = computed(() => props.variant === 'secondary' ? 'secondary' : 'primary')
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "sass:color";
|
||||
|
||||
button {
|
||||
margin: 5px 0 2.3em 0;
|
||||
width: 100%;
|
||||
padding: 1em 1.5em;
|
||||
border-radius: 0.5em;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
transition: 0.3s;
|
||||
background: blueviolet;
|
||||
text-align: center;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: color.adjust(blueviolet, $lightness: 15%);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background: #bbb;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
> div {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* Variants */
|
||||
button.secondary {
|
||||
background: gray;
|
||||
|
||||
&:hover {
|
||||
color: color.adjust(gray, $lightness: 15%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
93
app/components/button/burger.vue
Normal file
93
app/components/button/burger.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<script setup lang="ts">
|
||||
const burger = useBurgerStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button class="nav-button"
|
||||
@click="burger.toggle()"
|
||||
>
|
||||
<svg class="hamburger" :class="{ open: burger.checked }"
|
||||
viewBox="2 0 100 100">
|
||||
<path
|
||||
class="cross"
|
||||
style="fill:none;
|
||||
stroke-linecap:round;
|
||||
stroke-linejoin:round;
|
||||
stroke-opacity:1"
|
||||
d="M 36,21 H 74 L 74,33 55,52 36,71 36,83 H 74 L 74,71 36,33 Z"
|
||||
id="path978"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<path
|
||||
class="middle"
|
||||
style="fill:none;
|
||||
stroke-linecap:round;
|
||||
stroke-linejoin:bevel;
|
||||
stroke-opacity:1"
|
||||
d="M 36,52 H 74 C 90,52 82,69 77,74 71,80 63,83 55,83 38,83 24,69 24,52 24,35 38,21 55,21 c 17,0 31,14 31,31 0,9 -3,16 -9,22"
|
||||
id="path982"
|
||||
sodipodi:nodetypes="cccssssc" />
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Panel slide depuis la droite -->
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
button.nav-button{
|
||||
/*centering button*/
|
||||
display : block;
|
||||
position: absolute;
|
||||
bottom:5px;
|
||||
right:5px;
|
||||
border-radius: 5px;
|
||||
/*Formating Button*/
|
||||
width:3em;
|
||||
background-color:#aaaaaa80;
|
||||
border: none;
|
||||
|
||||
transition:1s;
|
||||
z-index: 10;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
& .hamburger{
|
||||
/*Default state*/
|
||||
& .cross, & .middle {
|
||||
stroke-width:7;
|
||||
transition:1s ;
|
||||
-moz-transition:1s ;
|
||||
-webkit-transition:1s ;
|
||||
stroke:black;
|
||||
}
|
||||
& .cross{
|
||||
stroke-dashoffset: 0 ;
|
||||
stroke-dasharray: 0 0 36 80 36 80;
|
||||
}
|
||||
|
||||
& .middle{
|
||||
stroke-dashoffset: 0 ;
|
||||
stroke-dasharray: 36 250;
|
||||
}
|
||||
/*Formating "open" state */
|
||||
&.open{
|
||||
& *{
|
||||
stroke:hsl(0, 100%, 30%);
|
||||
}
|
||||
& .cross{
|
||||
stroke-width:7;
|
||||
stroke-dashoffset: -61 ;
|
||||
stroke-dasharray: 33 82 33 79;
|
||||
}
|
||||
|
||||
& .middle{
|
||||
stroke-width:7;
|
||||
stroke-dashoffset: -60 ;
|
||||
stroke-dasharray: 270 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Navigation dans le panel
|
||||
|
||||
</style>
|
||||
38
app/components/button/google-challenge.vue
Normal file
38
app/components/button/google-challenge.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const userEmail = authStore.user?.email
|
||||
|
||||
const { isReady, login } = useCodeClient({
|
||||
// Force l'utilisateur à re-valider explicitement
|
||||
prompt: 'consent',
|
||||
login_hint: userEmail,
|
||||
|
||||
onSuccess: async (codeResponse) => {
|
||||
// 1. ICI, on reçoit un 'code' (ex: 4/0Afge...)
|
||||
console.log("Code reçu pour le BO:", codeResponse.code)
|
||||
|
||||
// 6. Envoi au BO pour échange contre sudo_token
|
||||
try {
|
||||
const result = await $fetch('/api/auth/google-sudo', {
|
||||
method: 'POST',
|
||||
body: { code: codeResponse.code }
|
||||
})
|
||||
// Ton BO pourra alors utiliser ce code pour valider l'identité
|
||||
} catch (err) {
|
||||
console.error("Erreur BO:", err)
|
||||
}
|
||||
},
|
||||
onError: (error) => console.error("Échec Sudo:", error)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
:disabled="!isReady"
|
||||
@click="() => login()"
|
||||
class="btn-sudo"
|
||||
>
|
||||
Vérification de sécurité via Google
|
||||
</button>
|
||||
</template>
|
||||
111
app/components/button/google.vue
Normal file
111
app/components/button/google.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
useCodeClient,
|
||||
type AuthCodeFlowSuccessResponse,
|
||||
type AuthCodeFlowErrorResponse
|
||||
} from "vue3-google-signin";
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const listStore = useListStore();
|
||||
|
||||
// On définit la fonction de succès avec le bon Type
|
||||
const handleSuccess = async (response: AuthCodeFlowSuccessResponse) => {
|
||||
|
||||
const googleCode = response.code;
|
||||
|
||||
try {
|
||||
// On envoie ce ticket à WordPress
|
||||
const data = await $fetch<any>('/api-wp/auth/google', {
|
||||
method: 'POST',
|
||||
body: { code: googleCode }
|
||||
});
|
||||
|
||||
// On stocke le JWT renvoyé par WordPress
|
||||
authStore.setTokenCookie(data.token);
|
||||
authStore.setUserCookie(data.user);
|
||||
listStore.lists = data.lists
|
||||
console.log(listStore.lists) //ok
|
||||
} catch (error) {
|
||||
console.error("Erreur côté WordPress:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleError = (error: AuthCodeFlowErrorResponse) => {
|
||||
console.error("L'utilisateur a fermé la fenêtre ou erreur Google:", error);
|
||||
};
|
||||
|
||||
// 3. On initialise le client spécifique au "Code"
|
||||
const { login } = useCodeClient({
|
||||
scope: 'openid email profile https://www.googleapis.com/auth/drive.appdata',
|
||||
access_type: 'offline',
|
||||
prompt: 'consent',
|
||||
onSuccess: handleSuccess,
|
||||
onError: handleError,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button @click="login" class="g-signin-button">
|
||||
<div class="g-logo-wrapper">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" class="g-logo">
|
||||
<path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/>
|
||||
<path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/>
|
||||
<path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/>
|
||||
<path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/>
|
||||
<path fill="none" d="M0 0h48v48H0z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="g-button-text">{{ $t('googleBtnTxt') }}</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.g-signin-button {
|
||||
margin:auto;
|
||||
margin-top:1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
background-color: #ffffff;
|
||||
color: #757575;
|
||||
height: 40px;
|
||||
width: auto;
|
||||
border: 1px solid #dadce0;
|
||||
border-radius: 4px;
|
||||
padding: 0em;
|
||||
font-family: 'Roboto', arial, sans-serif;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 1px 2px 0 rgba(60,64,67,0.302), 0 1px 3px 1px rgba(60,64,67,0.149);
|
||||
transition: background-color .218s, border-color .218s, box-shadow .218s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.g-signin-button:hover {
|
||||
background-color: hsl(210, 17%, 90%);
|
||||
border-color: #d2d2d2;
|
||||
box-shadow: 0 1px 2px 0 rgba(60,64,67,0.302), 0 1px 3px 1px rgba(60,64,67,0.149);
|
||||
}
|
||||
|
||||
.g-signin-button:active {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.g-logo-wrapper {
|
||||
padding: 11px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.g-logo {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.g-button-text {
|
||||
padding: 0 12px 0 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user