Merge 49409ba211a4c33f46a4e48843c7546359df954d into aae8bbdb3510697f541de4d58abc954d359b9391

This commit is contained in:
Saadani-Malek92 2025-02-09 16:14:22 +08:00 committed by GitHub
commit 4ed62cb7c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 582 additions and 16 deletions

View File

@ -9,6 +9,7 @@
},
"dependencies": {
"@popperjs/core": "2.11.5",
"axios": "^1.6.8",
"bootstrap": "5.1.3",
"pinia": "2.0.14",
"prismjs": "1.28.0",

View File

@ -1,18 +1,5 @@
<script setup>
/*
=========================================================
* Vue Material Kit 2 - v2.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/vue-material-kit
* Copyright 2022 Creative Tim (https://www.creative-tim.com)
Coded by www.creative-tim.com
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
import { RouterView } from "vue-router";
</script>

5
src/router/constants.js Normal file
View File

@ -0,0 +1,5 @@
export const Role = {
Admin: 'admin',
User: 'user',
Guest: 'guest',
};

View File

@ -23,6 +23,19 @@ import ElDropdowns from "../layouts/sections/elements/dropdowns/DropdownsView.vu
import ElProgressBars from "../layouts/sections/elements/progress-bars/ProgressBarsView.vue";
import ElToggles from "../layouts/sections/elements/toggles/TogglesView.vue";
import ElTypography from "../layouts/sections/elements/typography/TypographyView.vue";
import AdminLoginView from "../views/Auth/AdminLogin.vue";
import UserLoginView from "../views/Auth/UserLogin.vue";
import AdminDashboardView from "../views/Admin/dashboard.vue";
import AdminSettingsView from "../views/Admin/Settings.vue"
import AdminUsersView from "../views/Admin/Users.vue"
// import AdminView from "../views/LandingPages/Author/AuthorView.vue";
import { Role } from './constants';
import { useStore } from '@/stores'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
@ -30,6 +43,7 @@ const router = createRouter({
path: "/",
name: "presentation",
component: PresentationView,
//meta: { requiresAuth: true, requiredRole: Role.Admin },
},
{
path: "/pages/landing-pages/about-us",
@ -146,7 +160,100 @@ const router = createRouter({
name: "el-typography",
component: ElTypography,
},
],
});
{
path: '/admin/auth',
component: AdminLoginView,
name: "admin-login",
},
{
path: '/admin/dashboard',
component: AdminDashboardView,
name: "admin-dashboard",
export default router;
children: [
{
path: '/admin/users',
component: AdminUsersView,
name: "admin-users",
},
{
path: '/admin/settings',
component: AdminSettingsView,
name: "admin-settings",
},
// Other child routes for the dashboard
]
},
// {
// path: "/unauthorized",
// name: "unauthorized",
// component: UnauthorizedView,
// },
{
path: "/user/login",
name: "user-login",
component: UserLoginView,
},
],
});
router.beforeEach((to, from, next) => {
const store = useStore()
console.log(store.isAuthenticated,store.user,"store")
//console.log(store.isAuthenticated,"store")
if (to.meta.requiresAuth && !store.isAuthenticated) {
next('/admin/auth')
} else if (to.meta.requiresVisitor && store.isAuthenticated) {
next('/sections/elements/progress-bars')
} else {
next()
}
})
// function isAuthenticated() {
// // Check if the user is authenticated, e.g., by verifying the presence of a valid token or logged-in state
// // Return true if authenticated, false otherwise
// // Example: return localStorage.getItem('token') !== null;
// return true;
// }
// function getCurrentUserRole() {
// // Retrieve the current user's role from your authentication system or state management
// // Return the role of the current user
// // Example: return localStorage.getItem('userRole');
// return "guest";
// }
// // Route guard
// router.beforeEach((to, from, next) => {
// if (to.meta.requiresAuth) {
// // Check if the user is authenticated, e.g., by checking the presence of a valid token or logged-in state
// if (isAuthenticated()) {
// // Check if the user has the required role
// if (to.meta.requiredRole && getCurrentUserRole() !== to.meta.requiredRole) {
// // Redirect to a different route or show an error message
// next({ path: '/unauthorized' });
// } else {
// // Proceed to the requested route
// next();
// }
// } else {
// // Redirect to the login page or a suitable route for unauthenticated users
// next({ path: '/logout' });
// }
// } else {
// // No authentication required for the route
// next();
// }
// });
export default router;

View File

@ -1,7 +1,27 @@
import { defineStore } from "pinia";
import bootstrap from "bootstrap/dist/js/bootstrap.min.js";
export const useAppStore = defineStore("storeId", {
state: () => ({
bootstrap,
}),
});
export const useStore = defineStore({
id: 'main',
state: () => ({
isAuthenticated: false,
user: null,
}),
actions: {
login(user) {
this.isAuthenticated = true
this.user = user
},
logout() {
this.isAuthenticated = false
this.user = null
},
},
})

View File

@ -0,0 +1,3 @@
<template>
Settings Page
</template>

View File

@ -0,0 +1,44 @@
<template>
<div id="sidebar">
<ul class="nav">
<li>
<a class="nav-link" href="#" @click.prevent="goToPage('el-badges')" active-class="active">
<i class="zmdi zmdi-view-dashboard"></i> Dashboard
</a>
</li>
<li>
<a class="nav-link" href="#" @click.prevent="goToPage('admin-users')" >
<i class="zmdi zmdi-link"></i> Users
</a>
</li>
<li>
<a class="nav-link" href="#" @click.prevent="goToPage('admin-settings')">
<i class="zmdi zmdi-widgets"></i> Analytics
</a>
</li>
</ul>
</div>
</template>
<script>
export default {
methods: {
goToPage(page) {
this.$router.push({ name: page });
}
}
}
</script>

View File

@ -0,0 +1,3 @@
<template>
Users Page
</template>

View File

@ -0,0 +1,97 @@
<template>
<div id="viewport">
<Sidebar />
<div id="content">
<router-view />
<div class="container-fluid">
<h1>Simple Sidebar</h1>
<p>
Make sure to keep all page content within the
<code>#content</code>.
</p>
</div>
</div>
</div>
</template>
<script>
import Sidebar from './SideNavAdmin.vue';
export default {
components: { Sidebar }
}
</script>
<style scoped>/* Toggle Styles */
#viewport {
padding-left: 250px;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
#content {
width: 100%;
position: relative;
margin-right: 0;
}
/* Sidebar Styles */
#sidebar {
z-index: 1000;
position: fixed;
left: 250px;
width: 250px;
height: 100%;
margin-left: -250px;
overflow-y: auto;
background: #37474F;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
#sidebar header {
background-color: #263238;
font-size: 20px;
line-height: 52px;
text-align: center;
}
#sidebar header a {
color: #fff;
display: block;
text-decoration: none;
}
#sidebar header a:hover {
color: #fff;
}
#sidebar .nav{
}
#sidebar .nav a{
background: none;
border-bottom: 1px solid #455A64;
color: #CFD8DC;
font-size: 14px;
padding: 16px 24px;
}
#sidebar .nav a:hover{
background: none;
color: #ECEFF1;
}
#sidebar .nav a i{
margin-right: 16px;
}
</style>

View File

@ -0,0 +1,128 @@
<script setup>
import { onMounted } from "vue";
import Header from "@/examples/Header.vue";
import MaterialInput from "@/components/MaterialInput.vue";
import MaterialButton from "@/components/MaterialButton.vue";
import setMaterialInput from "@/assets/js/material-input";
import axios from "axios";
import { ref } from 'vue'
import { useStore } from '@/stores'
import router from '@/router'
onMounted(() => {
setMaterialInput();
});
const store = useStore()
const email = ref('')
const password = ref('')
const handleLogin = async () => {
try {
// Send a POST request to the login endpoint
const response = await axios.get('https://dummyjson.com/products/1', {
email: email.value,
password: password.value
})
// Check if the login was successful
console.log(response && response.status===200);
if (response && response.status===200) {
// Save the user to the store
store.login({
name: response.data.name,
email: response.data.email
})
// Navigate the user to the admin dashboard
router.push('/')
} else {
// Display an error message if the login failed
alert('Invalid email or password')
}
} catch (err) {
console.log('Error:', err);
}
};
</script>
<template>
<Header>
<div
class="page-header align-items-start min-vh-100"
:style="{
backgroundImage:
'url(https://images.unsplash.com/photo-1497294815431-9365093b7331?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1950&q=80)'
}"
loading="lazy"
>
<span class="mask bg-gradient-dark opacity-6"></span>
<div class="container my-auto">
<div class="row">
<div class="col-lg-4 col-md-8 col-12 mx-auto">
<div class="card z-index-0 fadeIn3 fadeInBottom">
<div
class="card-header p-0 position-relative mt-n4 mx-3 z-index-2"
>
<div
class="bg-gradient-info shadow-success border-radius-lg py-3 pe-1"
>
<h4
class="text-white font-weight-bolder text-center mt-2 mb-0"
>
Admin Sign in
</h4>
</div>
</div>
<div class="card-body">
<form role="form" class="text-start" @submit.prevent="handleLogin">
<MaterialInput
id="email"
class="input-group-outline my-3"
:label="{ text: 'Email', class: 'form-label' }"
type="email"
v-model="email"
/>
<MaterialInput
id="password"
class="input-group-outline mb-3"
:label="{ text: 'Password', class: 'form-label' }"
type="password"
v-model="password"
/>
<div class="text-center">
<MaterialButton
class="my-4 mb-2"
variant="gradient"
color="info"
fullWidth
@click="handleLogin"
>
Sign in
</MaterialButton>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<footer class="footer position-absolute bottom-2 py-2 w-100">
<div class="container">
<div class="row align-items-center justify-content-lg-between">
<div class="col-12 col-md-6 my-auto">
<div
class="copyright text-center text-sm text-white text-lg-start"
>
© {{ new Date().getFullYear() }}
</div>
</div>
</div>
</div>
</footer>
</div>
</Header>
</template>

View File

@ -0,0 +1,171 @@
<script setup>
import { onMounted } from "vue";
// example components
import DefaultNavbar from "@/examples/navbars/NavbarDefault.vue";
import Header from "@/examples/Header.vue";
//Vue Material Kit 2 components
import MaterialInput from "@/components/MaterialInput.vue";
import MaterialSwitch from "@/components/MaterialSwitch.vue";
import MaterialButton from "@/components/MaterialButton.vue";
// material-input
import setMaterialInput from "@/assets/js/material-input";
onMounted(() => {
setMaterialInput();
});
</script>
<template>
<DefaultNavbar transparent />
<Header>
<div
class="page-header align-items-start min-vh-100"
:style="{
backgroundImage:
'url(https://images.unsplash.com/photo-1497294815431-9365093b7331?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1950&q=80)'
}"
loading="lazy"
>
<span class="mask bg-gradient-dark opacity-6"></span>
<div class="container my-auto">
<div class="row">
<div class="col-lg-4 col-md-8 col-12 mx-auto">
<div class="card z-index-0 fadeIn3 fadeInBottom">
<div
class="card-header p-0 position-relative mt-n4 mx-3 z-index-2"
>
<div
class="bg-gradient-success shadow-success border-radius-lg py-3 pe-1"
>
<h4
class="text-white font-weight-bolder text-center mt-2 mb-0"
>
Sign in
</h4>
<div class="row mt-3">
<div class="col-2 text-center ms-auto">
<a class="btn btn-link px-3" href="javascript:;">
<i class="fa fa-facebook text-white text-lg"></i>
</a>
</div>
<div class="col-2 text-center px-1">
<a class="btn btn-link px-3" href="javascript:;">
<i class="fa fa-github text-white text-lg"></i>
</a>
</div>
<div class="col-2 text-center me-auto">
<a class="btn btn-link px-3" href="javascript:;">
<i class="fa fa-google text-white text-lg"></i>
</a>
</div>
</div>
</div>
</div>
<div class="card-body">
<form role="form" class="text-start">
<MaterialInput
id="email"
class="input-group-outline my-3"
:label="{ text: 'Email', class: 'form-label' }"
type="email"
/>
<MaterialInput
id="password"
class="input-group-outline mb-3"
:label="{ text: 'Password', class: 'form-label' }"
type="password"
/>
<MaterialSwitch
class="d-flex align-items-center mb-3"
id="rememberMe"
labelClass="mb-0 ms-3"
checked
>Remember me</MaterialSwitch
>
<div class="text-center">
<MaterialButton
class="my-4 mb-2"
variant="gradient"
color="success"
fullWidth
>Sign in</MaterialButton
>
</div>
<p class="mt-4 text-sm text-center">
Don't have an account?
<a
href="#"
class="text-success text-gradient font-weight-bold"
>Sign up</a
>
</p>
</form>
</div>
</div>
</div>
</div>
</div>
<footer class="footer position-absolute bottom-2 py-2 w-100">
<div class="container">
<div class="row align-items-center justify-content-lg-between">
<div class="col-12 col-md-6 my-auto">
<div
class="copyright text-center text-sm text-white text-lg-start"
>
© {{ new Date().getFullYear() }}, made with
<i class="fa fa-heart" aria-hidden="true"></i> by
<a
href="https://www.creative-tim.com"
class="font-weight-bold text-white"
target="_blank"
>Creative Tim</a
>
for a better web.
</div>
</div>
<div class="col-12 col-md-6">
<ul
class="nav nav-footer justify-content-center justify-content-lg-end"
>
<li class="nav-item">
<a
href="https://www.creative-tim.com"
class="nav-link text-white"
target="_blank"
>Creative Tim</a
>
</li>
<li class="nav-item">
<a
href="https://www.creative-tim.com/presentation"
class="nav-link text-white"
target="_blank"
>About Us</a
>
</li>
<li class="nav-item">
<a
href="https://www.creative-tim.com/blog"
class="nav-link text-white"
target="_blank"
>Blog</a
>
</li>
<li class="nav-item">
<a
href="https://www.creative-tim.com/license"
class="nav-link pe-0 text-white"
target="_blank"
>License</a
>
</li>
</ul>
</div>
</div>
</div>
</footer>
</div>
</Header>
</template>