Compare commits

...

2 Commits

6 changed files with 146 additions and 46 deletions

View File

@ -1,4 +1,4 @@
import { useAuthStore } from "@/stores";
import { useAuthStore, useAlertStore } from "@/stores";
export const fetchWrapper = {
get: request("GET"),
@ -51,7 +51,14 @@ async function handleResponse(response) {
}
// get error message from body or default to response status
const error = (data && data.message) || response.status;
// const error = (data && data.message) || response.status;
const error = data["error"];
//TODO: need standard messages
console.log("error: ", error);
const alertStore = useAlertStore();
alertStore.error(error);
return Promise.reject(error);
}

View File

@ -198,8 +198,12 @@
<HelpCircleIcon class="w-4 h-4 mr-2" /> Help</DropdownItem
>
<DropdownDivider class="border-white/[0.08]" />
<DropdownItem class="dropdown-item hover:bg-white/5">
<ToggleRightIcon class="w-4 h-4 mr-2" /> Logout</DropdownItem
<DropdownItem
class="dropdown-item hover:bg-white/5"
@click="onLogout"
>
<ToggleRightIcon class="w-4 h-4 mr-2" />
Logout</DropdownItem
>
</DropdownContent>
</DropdownMenu>
@ -212,6 +216,7 @@
<script setup>
import { ref } from "vue";
import { useAuthStore } from "@/stores";
const searchDropdown = ref(false);
const showSearchDropdown = () => {
@ -220,4 +225,10 @@ const showSearchDropdown = () => {
const hideSearchDropdown = () => {
searchDropdown.value = false;
};
const onLogout = () => {
console.log("Logout");
const authStore = useAuthStore();
return authStore.logout();
};
</script>

2
src/helpers/constants.js Normal file
View File

@ -0,0 +1,2 @@
// localStorage items
export const USER = "user";

1
src/helpers/index.js Normal file
View File

@ -0,0 +1 @@
export * from "./constants";

View File

@ -1,8 +1,7 @@
import { defineStore } from "pinia";
import { fetchWrapper } from "@/api";
// import { router } from "@/router";
import { useAlertStore } from "@/stores";
import router from "@/router";
import { USER } from "@/helpers";
const baseUrl = `${import.meta.env.VITE_API_URL}/api`;
@ -10,7 +9,7 @@ export const useAuthStore = defineStore({
id: "auth",
state: () => ({
// initialize state from local storage to enable user to stay logged in
user: JSON.parse(localStorage.getItem("user")),
user: JSON.parse(localStorage.getItem(USER)),
returnUrl: null,
}),
actions: {
@ -18,22 +17,20 @@ export const useAuthStore = defineStore({
return fetchWrapper
.post(`${baseUrl}/login`, { email, password })
.then((response) => {
console.log("response: " + response);
// get user
let client = response["success"]["client"];
console.log("user: " + response["success"]["token"]["plainTextToken"]);
// add user token
client["token"] = response["success"]["token"]["plainTextToken"];
// update pinia state
this.user = user;
this.user = client;
// store user details and jwt in local storage to keep user logged in between page refreshes
// localStorage.setItem("user", JSON.stringify(user));
localStorage.setItem(USER, JSON.stringify(this.user));
// redirect to previous url or default to home page
// router.push(this.returnUrl || "/");
})
.catch((error) => {
const alertStore = useAlertStore();
alertStore.error(error);
// redirect to home page
router.push({ path: "/" });
});
},
async register(newUser) {
@ -59,9 +56,9 @@ export const useAuthStore = defineStore({
});
},
logout() {
// this.user = null;
// localStorage.removeItem("user");
// router.push("/account/login");
this.user = null;
localStorage.removeItem(USER);
router.push({ path: "/login" });
},
},
});

View File

@ -6,17 +6,28 @@
<!-- BEGIN: Login Info -->
<div class="hidden xl:flex flex-col min-h-screen">
<a href="" class="-intro-x flex items-center pt-5">
<img alt="Midone Tailwind HTML Admin Template" class="w-6" src="@/assets/images/logo.svg" />
<img
alt="Midone Tailwind HTML Admin Template"
class="w-6"
src="@/assets/images/logo.svg"
/>
<span class="text-white text-lg ml-3"> Icewall </span>
</a>
<div class="my-auto">
<img alt="Midone Tailwind HTML Admin Template" class="-intro-x w-1/2 -mt-16"
src="@/assets/images/illustration.svg" />
<div class="-intro-x text-white font-medium text-4xl leading-tight mt-10">
<img
alt="Midone Tailwind HTML Admin Template"
class="-intro-x w-1/2 -mt-16"
src="@/assets/images/illustration.svg"
/>
<div
class="-intro-x text-white font-medium text-4xl leading-tight mt-10"
>
A few more clicks to <br />
sign in to your account.
</div>
<div class="-intro-x mt-5 text-lg text-white text-opacity-70 dark:text-slate-400">
<div
class="-intro-x mt-5 text-lg text-white text-opacity-70 dark:text-slate-400"
>
Manage all your e-commerce accounts in one place
</div>
</div>
@ -25,39 +36,90 @@
<!-- BEGIN: Login Form -->
<div class="h-screen xl:h-auto flex py-5 xl:py-0 my-10 xl:my-0">
<div
class="my-auto mx-auto xl:ml-20 bg-white dark:bg-darkmode-600 xl:bg-transparent px-5 sm:px-8 py-8 xl:p-0 rounded-md shadow-md xl:shadow-none w-full sm:w-3/4 lg:w-2/4 xl:w-auto">
<h2 class="intro-x font-bold text-2xl xl:text-3xl text-center xl:text-left">
class="my-auto mx-auto xl:ml-20 bg-white dark:bg-darkmode-600 xl:bg-transparent px-5 sm:px-8 py-8 xl:p-0 rounded-md shadow-md xl:shadow-none w-full sm:w-3/4 lg:w-2/4 xl:w-auto"
>
<h2
class="intro-x font-bold text-2xl xl:text-3xl text-center xl:text-left"
>
Sign In
</h2>
<div class="intro-x mt-2 text-slate-400 xl:hidden text-center">
A few more clicks to sign in to your account. Manage all your e-commerce
accounts in one place
A few more clicks to sign in to your account. Manage all your
e-commerce accounts in one place
</div>
<div class="intro-x mt-8">
<input type="text" class="intro-x login__input form-control py-3 px-4 block" placeholder="Email" />
<input type="password" class="intro-x login__input form-control py-3 px-4 block mt-4"
placeholder="Password" />
<input
type="text"
v-model.trim="validate.email.$model"
class="intro-x login__input form-control py-3 px-4 block mt-4"
:class="{ 'border-danger': validate.email.$error }"
placeholder="Email"
/>
<template v-if="validate.email.$error">
<div
v-for="(error, index) in validate.email.$errors"
:key="index"
class="text-danger mt-2"
>
{{ error.$message }}
</div>
</template>
<input
type="password"
v-model.trim="validate.password.$model"
class="intro-x login__input form-control py-3 px-4 block mt-4"
:class="{ 'border-danger': validate.password.$error }"
placeholder="Password"
/>
<template v-if="validate.password.$error">
<div
v-for="(error, index) in validate.password.$errors"
:key="index"
class="text-danger mt-2"
>
{{ error.$message }}
</div>
</template>
</div>
<div class="intro-x flex text-slate-600 dark:text-slate-500 text-xs sm:text-sm mt-4">
<div
class="intro-x flex text-slate-600 dark:text-slate-500 text-xs sm:text-sm mt-4"
>
<div class="flex items-center mr-auto">
<input id="remember-me" type="checkbox" class="form-check-input border mr-2" />
<label class="cursor-pointer select-none" for="remember-me">Remember me</label>
<input
id="remember-me"
type="checkbox"
class="form-check-input border mr-2"
/>
<label class="cursor-pointer select-none" for="remember-me"
>Remember me</label
>
</div>
<a href="">Forgot Password?</a>
</div>
<div class="intro-x mt-5 xl:mt-8 text-center xl:text-left">
<button class="btn btn-primary py-3 px-4 w-full xl:w-32 xl:mr-3 align-top" @click.prevent="onSubmit">
<button
class="btn btn-primary py-3 px-4 w-full xl:w-32 xl:mr-3 align-top"
@click.prevent="onSubmit"
>
Login
</button>
<button class="btn btn-outline-secondary py-3 px-4 w-full xl:w-32 mt-3 xl:mt-0 align-top">
<button
class="btn btn-outline-secondary py-3 px-4 w-full xl:w-32 mt-3 xl:mt-0 align-top"
>
Register
</button>
</div>
<div class="intro-x mt-10 xl:mt-24 text-slate-600 dark:text-slate-500 text-center xl:text-left">
<div
class="intro-x mt-10 xl:mt-24 text-slate-600 dark:text-slate-500 text-center xl:text-left"
>
By signin up, you agree to our
<a class="text-primary dark:text-slate-200" href="">Terms and Conditions</a>
<a class="text-primary dark:text-slate-200" href=""
>Terms and Conditions</a
>
&
<a class="text-primary dark:text-slate-200" href="">Privacy Policy</a>
<a class="text-primary dark:text-slate-200" href=""
>Privacy Policy</a
>
</div>
</div>
</div>
@ -68,16 +130,36 @@
</template>
<script setup>
import { onMounted } from "vue";
import { onMounted, reactive, toRefs } from "vue";
import DarkModeSwitcher from "@/components/dark-mode-switcher/Main.vue";
import dom from "@left4code/tw-starter/dist/js/dom";
import { useAuthStore } from '@/stores'
import { useVuelidate } from "@vuelidate/core";
import { required, minLength, email } from "@vuelidate/validators";
import { useAuthStore } from "@/stores";
const formData = reactive({
email: "",
password: "",
});
const rules = {
email: {
required,
email,
},
password: {
required,
minLength: minLength(8),
},
};
const validate = useVuelidate(rules, toRefs(formData));
const onSubmit = () => {
console.log("onSubmit");
console.log("onSubmit", formData.email, " ", formData.password);
const authStore = useAuthStore();
// const { username, password } = values;
return authStore.login("ilmedovamahri@gmail.com", "12345678");
return authStore.login(formData.email, formData.password);
};
onMounted(() => {