Compare commits
2 Commits
f11e2502dd
...
14a156d929
Author | SHA1 | Date | |
---|---|---|---|
14a156d929 | |||
0ce48776f1 |
@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<NuxtRouteAnnouncer />
|
<NuxtRouteAnnouncer />
|
||||||
<NuxtWelcome />
|
<NavBar />
|
||||||
|
<NuxtPage />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
22
frontend/components/Avatar.vue
Normal file
22
frontend/components/Avatar.vue
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<div class="avatar">
|
||||||
|
<div class="rounded-full">
|
||||||
|
<img :src="getAvatarUrl(user)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { User } from '~/types/user';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
user: User,
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const getAvatarUrl = (user: User) => {
|
||||||
|
if (user.avatar) {
|
||||||
|
return user.avatar;
|
||||||
|
}
|
||||||
|
return 'https://avatar.iran.liara.run/username?username=' + user.name;
|
||||||
|
};
|
||||||
|
</script>
|
71
frontend/components/LoginModal.vue
Normal file
71
frontend/components/LoginModal.vue
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<dialog
|
||||||
|
id="login_modal"
|
||||||
|
ref="login_modal"
|
||||||
|
@cancel.prevent=""
|
||||||
|
@keyup="handleKeyPress"
|
||||||
|
class="modal"
|
||||||
|
>
|
||||||
|
<div class="modal-box">
|
||||||
|
<h3 class="text-3xl text-center mb-6">Connexion</h3>
|
||||||
|
<div class="flex flex-wrap gap-5 justify-center">
|
||||||
|
<template v-for="(user, index) in users" :key="user.id">
|
||||||
|
<LoginModalAvatar
|
||||||
|
:user="user"
|
||||||
|
:rank="index+1"
|
||||||
|
@selectUser="login"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form method="dialog" class="modal-backdrop">
|
||||||
|
<button class="cursor-default">close</button>
|
||||||
|
</form>
|
||||||
|
</dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { User } from '~/types/user';
|
||||||
|
|
||||||
|
const users: User[] = [
|
||||||
|
{ id: 1, name: 'John Doe', avatar: 'https://img.daisyui.com/images/stock/photo-1534528741775-53994a69daeb.webp' },
|
||||||
|
{ id: 2, name: 'Jane Doe', avatar: 'https://avatar.iran.liara.run/public' },
|
||||||
|
{ id: 3, name: 'Michel Moulin', avatar: '' },
|
||||||
|
{ id: 4, name: 'Jean Paris', avatar: '' },
|
||||||
|
{ id: 5, name: 'Marie Dupont', avatar: '' },
|
||||||
|
{ id: 6, name: 'Émilie Fournier', avatar: '' },
|
||||||
|
{ id: 7, name: 'Pierre Lefevre', avatar: '' },
|
||||||
|
{ id: 8, name: 'Sophie Lemoine', avatar: '' },
|
||||||
|
{ id: 9, name: 'Lucie Simon', avatar: '' },
|
||||||
|
{ id: 10, name: 'Kevin Boucher', avatar: '' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const loginModal = useTemplateRef('login_modal');
|
||||||
|
|
||||||
|
const current_user = useCurrentUser();
|
||||||
|
|
||||||
|
const login = (user: User) => {
|
||||||
|
console.log('login', user);
|
||||||
|
current_user.value = user;
|
||||||
|
loginModal.value?.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyPress = (event: KeyboardEvent) => {
|
||||||
|
// Extract the rank from the event.code : Digit7 -> 7
|
||||||
|
const rank = event.code.match(/\d/);
|
||||||
|
if (!rank) {
|
||||||
|
console.debug('Not handled key event', { event });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const user = getUserByRank(parseInt(rank[0]));
|
||||||
|
if (user) {
|
||||||
|
login(user);
|
||||||
|
} else {
|
||||||
|
console.debug('Not handled key event', { event });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUserByRank = (rank: number): User => {
|
||||||
|
return users[rank - 1];
|
||||||
|
};
|
||||||
|
</script>
|
17
frontend/components/LoginModalAvatar.vue
Normal file
17
frontend/components/LoginModalAvatar.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<button class="relative" @click="$emit('selectUser', user)">
|
||||||
|
<Avatar class="w-24" :user="user" />
|
||||||
|
<div class="absolute w-fit mx-auto bottom-0 inset-x-0">
|
||||||
|
<kbd class="kbd kbd-sm">{{ rank }}</kbd>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { User } from '~/types/user';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
user: User,
|
||||||
|
rank: Number,
|
||||||
|
}>();
|
||||||
|
</script>
|
35
frontend/components/NavBar.vue
Normal file
35
frontend/components/NavBar.vue
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<div class="navbar">
|
||||||
|
<div class="navbar-start">
|
||||||
|
<a class="btn btn-ghost text-xl" href="/">Chrys4lide</a>
|
||||||
|
</div>
|
||||||
|
<nav class="navbar-center">
|
||||||
|
<NuxtLink to="/" class="btn btn-ghost">Accueil</NuxtLink>
|
||||||
|
<NuxtLink to="/CPS" class="btn btn-ghost">Carte CPS</NuxtLink>
|
||||||
|
</nav>
|
||||||
|
<div class="navbar-end">
|
||||||
|
<template v-if="!current_user">
|
||||||
|
<button class="btn btn-ghost" type="button" onclick="login_modal.showModal()">
|
||||||
|
Connexion
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<details class="dropdown dropdown-end">
|
||||||
|
<summary class="block"><Avatar :user="current_user" class="w-12" role="button" /></summary>
|
||||||
|
<ul class="menu dropdown-content bg-base-100 rounded-box z-[1] w-52 p-2 shadow">
|
||||||
|
<li><a @click="logout">Déconnexion</a></li>
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<LoginModal />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const current_user = useCurrentUser();
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
current_user.value = null;
|
||||||
|
};
|
||||||
|
</script>
|
3
frontend/composables/currentUser.ts
Normal file
3
frontend/composables/currentUser.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import type { User } from '@/types/user';
|
||||||
|
|
||||||
|
export const useCurrentUser = () => useState<User | null>('currentUser', () => null);
|
8
frontend/pages/CPS.vue
Normal file
8
frontend/pages/CPS.vue
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1 class="text-xl">Carte CPS</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
</script>
|
17
frontend/pages/index.vue
Normal file
17
frontend/pages/index.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1 class="text-xl">Welcome to your {{ appName }}!</h1>
|
||||||
|
<p v-if="current_user">Logged in as {{ current_user.name }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const current_user = useCurrentUser();
|
||||||
|
const appName = 'Nuxt App';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
h1 {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
</style>
|
6
frontend/types/user.ts
Normal file
6
frontend/types/user.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export declare interface User {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
email?: string;
|
||||||
|
avatar?: string;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user