mirror of
https://github.com/creativetimofficial/vue-material-kit.git
synced 2025-05-24 05:24:21 +08:00
Merge 49409ba211a4c33f46a4e48843c7546359df954d into 89e91169177213ef6668bff2c90eb27f1f502257
This commit is contained in:
commit
7999de878a
@ -9,6 +9,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@popperjs/core": "2.11.5",
|
"@popperjs/core": "2.11.5",
|
||||||
|
"axios": "^1.6.8",
|
||||||
"bootstrap": "5.1.3",
|
"bootstrap": "5.1.3",
|
||||||
"pinia": "2.0.14",
|
"pinia": "2.0.14",
|
||||||
"prismjs": "1.28.0",
|
"prismjs": "1.28.0",
|
||||||
|
13
src/App.vue
13
src/App.vue
@ -1,18 +1,5 @@
|
|||||||
<script setup>
|
<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";
|
import { RouterView } from "vue-router";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
5
src/router/constants.js
Normal file
5
src/router/constants.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export const Role = {
|
||||||
|
Admin: 'admin',
|
||||||
|
User: 'user',
|
||||||
|
Guest: 'guest',
|
||||||
|
};
|
@ -23,6 +23,19 @@ import ElDropdowns from "../layouts/sections/elements/dropdowns/DropdownsView.vu
|
|||||||
import ElProgressBars from "../layouts/sections/elements/progress-bars/ProgressBarsView.vue";
|
import ElProgressBars from "../layouts/sections/elements/progress-bars/ProgressBarsView.vue";
|
||||||
import ElToggles from "../layouts/sections/elements/toggles/TogglesView.vue";
|
import ElToggles from "../layouts/sections/elements/toggles/TogglesView.vue";
|
||||||
import ElTypography from "../layouts/sections/elements/typography/TypographyView.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({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes: [
|
routes: [
|
||||||
@ -30,6 +43,7 @@ const router = createRouter({
|
|||||||
path: "/",
|
path: "/",
|
||||||
name: "presentation",
|
name: "presentation",
|
||||||
component: PresentationView,
|
component: PresentationView,
|
||||||
|
//meta: { requiresAuth: true, requiredRole: Role.Admin },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/pages/landing-pages/about-us",
|
path: "/pages/landing-pages/about-us",
|
||||||
@ -146,7 +160,100 @@ const router = createRouter({
|
|||||||
name: "el-typography",
|
name: "el-typography",
|
||||||
component: ElTypography,
|
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;
|
||||||
|
|
@ -1,7 +1,27 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import bootstrap from "bootstrap/dist/js/bootstrap.min.js";
|
import bootstrap from "bootstrap/dist/js/bootstrap.min.js";
|
||||||
|
|
||||||
export const useAppStore = defineStore("storeId", {
|
export const useAppStore = defineStore("storeId", {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
bootstrap,
|
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
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
3
src/views/Admin/Settings.vue
Normal file
3
src/views/Admin/Settings.vue
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
Settings Page
|
||||||
|
</template>
|
44
src/views/Admin/SideNavAdmin.vue
Normal file
44
src/views/Admin/SideNavAdmin.vue
Normal 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>
|
||||||
|
|
3
src/views/Admin/Users.vue
Normal file
3
src/views/Admin/Users.vue
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
Users Page
|
||||||
|
</template>
|
97
src/views/Admin/dashboard.vue
Normal file
97
src/views/Admin/dashboard.vue
Normal 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>
|
128
src/views/Auth/AdminLogin.vue
Normal file
128
src/views/Auth/AdminLogin.vue
Normal 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>
|
171
src/views/Auth/UserLogin.vue
Normal file
171
src/views/Auth/UserLogin.vue
Normal 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>
|
Loading…
x
Reference in New Issue
Block a user