Icônes + CSS et intégration Backend
This commit is contained in:
20
src/App.vue
20
src/App.vue
@@ -1,5 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterView, RouterLink } from 'vue-router'
|
||||
import { ref, provide, onMounted } from 'vue'
|
||||
import { checkUser } from '@/utils/discord'
|
||||
import type { Ref } from 'vue'
|
||||
import type { User } from '@/utils/discord'
|
||||
|
||||
// État de l'utilisateur et de son avatar
|
||||
const user: Ref<User | null> = ref(null)
|
||||
const avatar = ref('')
|
||||
|
||||
provide('user', user) // Fournit l'utilisateur aux composants enfants
|
||||
|
||||
onMounted(async () => {
|
||||
user.value = await checkUser() // Vérifie l'authentification lors du montage du composant
|
||||
avatar.value = user.value ? `https://cdn.discordapp.com/avatars/${user.value.id}/${user.value.avatar}?size=48` : ''
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -12,6 +27,7 @@ import { RouterView, RouterLink } from 'vue-router'
|
||||
<router-link to="/">Index</router-link>
|
||||
<p>|</p>
|
||||
<router-link to="/discord">Discord</router-link>
|
||||
<img v-if="user" :src=avatar>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
@@ -50,6 +66,10 @@ nav * {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
nav img {
|
||||
border-radius: 20%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
left: 0;
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition:
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
/* VUE STYLE */
|
||||
#app {
|
||||
/* max-width: 1280px; */
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
/* margin: 0 auto; */
|
||||
/* padding: 2rem;*/
|
||||
height: inherit;
|
||||
width: inherit;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@@ -29,8 +31,8 @@ a,
|
||||
}
|
||||
|
||||
#app {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
/* display: grid; */
|
||||
/* grid-template-columns: 1fr 1fr; */
|
||||
padding: 0 2rem;
|
||||
}
|
||||
}
|
||||
@@ -61,7 +63,10 @@ a,
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-left: 200px; /* 200px is the width of the header vl position */
|
||||
margin-top: 60px; /* 60px is the height of the header navbar */
|
||||
height: calc(100% - 60px);
|
||||
margin-left: 200px; /* 200px is the width of the header vl position (or sidebar) */
|
||||
width: calc(100% - 200px);
|
||||
/* padding: 0px 10px; */
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { fas } from '@fortawesome/free-solid-svg-icons'
|
||||
import { fab } from '@fortawesome/free-brands-svg-icons'
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import cookies from 'vue-cookies'
|
||||
|
||||
import App from './App.vue'
|
||||
@@ -12,6 +14,8 @@ import './assets/main.css'
|
||||
library.add(fas, fab)
|
||||
|
||||
createApp(App)
|
||||
.use(createPinia())
|
||||
.use(createI18n({}))
|
||||
.use(router)
|
||||
.use(cookies)
|
||||
.component('font-awesome-icon', FontAwesomeIcon)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { inject } from 'vue'
|
||||
import type { VueCookies } from 'vue-cookies'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
@@ -9,6 +7,7 @@ const router = createRouter({
|
||||
path: '/',
|
||||
name: 'index',
|
||||
component: () => import('../views/IndexView.vue'),
|
||||
meta: { title: 'MainFrame' },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
@@ -26,7 +25,7 @@ const router = createRouter({
|
||||
path: '/discord',
|
||||
name: 'discord',
|
||||
component: () => import('../views/DiscordView.vue'),
|
||||
meta: { discordAuth: true },
|
||||
meta: { title: 'MainFrame | Discord', discordAuth: true },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
@@ -43,15 +42,9 @@ const router = createRouter({
|
||||
]
|
||||
})
|
||||
|
||||
router.beforeEach((to) => {
|
||||
const $cookies = inject<VueCookies>('$cookies')
|
||||
if (!$cookies) return console.log('Error: $cookies is not injected')
|
||||
|
||||
if (to.meta.discordAuth && !$cookies.isKey('DISCORD_CODE')) {
|
||||
window.location.href =
|
||||
'https://discord.com/oauth2/authorize?client_id=1274800564449841172&response_type=code&redirect_uri=https%3A%2F%2Fmainframe.zac.ovh%2Fdiscord&scope=identify'
|
||||
return
|
||||
}
|
||||
router.beforeEach((to, from, next) => {
|
||||
document.title = to.meta.title as string
|
||||
next()
|
||||
})
|
||||
|
||||
export default router
|
||||
|
||||
58
src/utils/discord.ts
Normal file
58
src/utils/discord.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export interface User {
|
||||
id: string
|
||||
username: string
|
||||
discriminator: string
|
||||
global_name?: string
|
||||
avatar?: string
|
||||
bot?: boolean
|
||||
system?: boolean
|
||||
mfa_enabled?: boolean
|
||||
banner?: string
|
||||
accent_color?: number
|
||||
locale?: string
|
||||
verified?: boolean
|
||||
email?: string
|
||||
flags?: number
|
||||
premium_type?: number
|
||||
public_flags?: number
|
||||
avatar_decoration_data?: {
|
||||
sku_id: number
|
||||
asset: string
|
||||
}
|
||||
}
|
||||
|
||||
// Fonction pour rediriger vers Discord pour l'authentification
|
||||
export function login() {
|
||||
window.location.href = import.meta.env.VITE_BACKEND_URL + '/discord/auth/redirect';
|
||||
}
|
||||
|
||||
// Fonction pour se déconnecter
|
||||
export function logout(user_value: User | null) {
|
||||
user_value = null
|
||||
return user_value
|
||||
// Effectue une requête à ton API pour déconnecter l'utilisateur, supprimer la session, etc.
|
||||
// Ou simplement rediriger vers une page d'accueil sans session
|
||||
}
|
||||
|
||||
export async function checkBots() {
|
||||
try {
|
||||
const response = await axios.get(import.meta.env.VITE_BACKEND_URL + '/discord/bots', { withCredentials: true })
|
||||
return response.data
|
||||
} catch (err) { return null }
|
||||
}
|
||||
|
||||
export async function checkUser() {
|
||||
try {
|
||||
const response = await axios.get(import.meta.env.VITE_BACKEND_URL + '/discord/user', { withCredentials: true })
|
||||
return response.data
|
||||
} catch (err) { return null }
|
||||
}
|
||||
|
||||
export async function checkUserGuilds() {
|
||||
try {
|
||||
const response = await axios.get(import.meta.env.VITE_BACKEND_URL + '/discord/user/guilds', { withCredentials: true })
|
||||
return response.data
|
||||
} catch (err) { return null }
|
||||
}
|
||||
@@ -1,5 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { inject } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
import type { User } from '@/utils/discord'
|
||||
|
||||
const user: Ref<User | null> | undefined = inject('user')
|
||||
const bots: Ref<User[] | null> | undefined = inject('bots')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<h1>Test Dashboard Discord</h1>
|
||||
<div class="title">
|
||||
<h1>Test Dashboard Discord</h1>
|
||||
<div v-if="user">
|
||||
<p>Vous êtes connecté en tant que {{ user.global_name }}.</p>
|
||||
<p>Vous avez l'ID {{ user.id }}.</p>
|
||||
</div>
|
||||
<p v-else>Vous n'êtes pas connecté.</p>
|
||||
</div>
|
||||
<div class="bots">
|
||||
<h2>Bots</h2>
|
||||
<div v-for="bot in bots" :key="bot.id">
|
||||
<p>{{ bot.username }}</p>
|
||||
<p>{{ bot.id }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,13 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterLink, RouterView, useRoute } from 'vue-router'
|
||||
import { inject } from 'vue'
|
||||
import type { VueCookies } from 'vue-cookies'
|
||||
import { RouterLink, RouterView } from 'vue-router'
|
||||
import { checkBots, checkUserGuilds, login, logout } from '@/utils/discord'
|
||||
import { ref, provide, inject, onMounted } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
import type { User } from '@/utils/discord'
|
||||
|
||||
const $route = useRoute()
|
||||
const $cookies = inject<VueCookies>('$cookies')
|
||||
if (!$cookies) throw new Error('Missing VueCookies')
|
||||
// État de l'utilisateur et des bots
|
||||
const user: Ref<User | null> | undefined = inject('user')
|
||||
const bots = ref([])
|
||||
const guilds = ref([])
|
||||
|
||||
if ($route.query.code) $cookies.set('DISCORD_CODE', $route.query.code, '30d', '/discord', 'mainframe.zac.ovh', true, 'Strict')
|
||||
provide('bots', bots) // Fournit les bots aux composants enfants
|
||||
provide('guilds', guilds) // Fournit les guilds aux composants enfants
|
||||
|
||||
onMounted(async () => {
|
||||
if (user) {
|
||||
bots.value = await checkBots()
|
||||
guilds.value = await checkUserGuilds()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -15,6 +26,8 @@ if ($route.query.code) $cookies.set('DISCORD_CODE', $route.query.code, '30d', '/
|
||||
<div class="sidenav">
|
||||
<router-link to="/discord">Dashboard</router-link>
|
||||
<router-link to="/config">Config</router-link>
|
||||
<button v-if="!user" @click="login">Se connecter</button>
|
||||
<button v-if="user" @click="logout(user)">Se déconnecter</button>
|
||||
</div>
|
||||
|
||||
<router-view v-slot="{ Component }">
|
||||
@@ -23,4 +36,11 @@ if ($route.query.code) $cookies.set('DISCORD_CODE', $route.query.code, '30d', '/
|
||||
</transition>
|
||||
</router-view>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.sidenav button {
|
||||
position: absolute;
|
||||
bottom: 60px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user