cleanup
This commit is contained in:
@@ -30,7 +30,7 @@ defineProps({
|
||||
align-self: center;
|
||||
|
||||
.sm-message {
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
padding: map-get($spacer, 2) map-get($spacer, 3);
|
||||
margin-bottom: map-get($spacer, 4);
|
||||
text-align: center;
|
||||
@@ -69,6 +69,7 @@ defineProps({
|
||||
justify-content: center;
|
||||
align-self: center;
|
||||
white-space: pre-wrap;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ const menuItems = [
|
||||
},
|
||||
{
|
||||
name: "contact",
|
||||
label: "Contact us",
|
||||
label: "Contact",
|
||||
to: { name: "contact" },
|
||||
icon: "mail-outline",
|
||||
},
|
||||
|
||||
@@ -20,7 +20,7 @@ interface ApiOptions {
|
||||
export interface ApiResponse {
|
||||
status: number;
|
||||
message: string;
|
||||
data: unknown;
|
||||
data: Record<string, unknown>;
|
||||
json?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,3 +64,8 @@ export interface UserResponse {
|
||||
export interface UserCollection {
|
||||
users: Array<User>;
|
||||
}
|
||||
|
||||
export interface LoginResponse {
|
||||
user: User;
|
||||
token: string;
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import {
|
||||
type FormObjectValidateFunction = (item: string | null) => boolean;
|
||||
type FormObjectLoadingFunction = (state: boolean) => void;
|
||||
type FormObjectMessageFunction = (
|
||||
message: string,
|
||||
type: string,
|
||||
icon: string
|
||||
message?: string,
|
||||
type?: string,
|
||||
icon?: string
|
||||
) => void;
|
||||
type FormObjectErrorFunction = (message: string) => void;
|
||||
type FormObjectApiErrorsFunction = (apiErrors: ApiResponse) => void;
|
||||
@@ -77,21 +77,19 @@ const defaultFormObject: FormObject = {
|
||||
let foundKeys = false;
|
||||
|
||||
if (
|
||||
apiResponse.json &&
|
||||
typeof apiResponse.json === "object" &&
|
||||
apiResponse.json.errors
|
||||
apiResponse.data &&
|
||||
typeof apiResponse.data === "object" &&
|
||||
apiResponse.data.errors
|
||||
) {
|
||||
const errors = apiResponse.json.errors as Record<string, string>;
|
||||
const errors = apiResponse.data.errors as Record<string, string>;
|
||||
Object.keys(errors).forEach((key) => {
|
||||
if (
|
||||
typeof this[key] === "object" &&
|
||||
Object.keys(this[key]).includes("validation")
|
||||
typeof this.controls[key] === "object" &&
|
||||
Object.keys(this.controls[key]).includes("validation")
|
||||
) {
|
||||
foundKeys = true;
|
||||
this[key].validation.result = createValidationResult(
|
||||
false,
|
||||
errors[key]
|
||||
);
|
||||
this.controls[key].validation.result =
|
||||
createValidationResult(false, errors[key]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ export const routes = [
|
||||
path: "/contact",
|
||||
name: "contact",
|
||||
meta: {
|
||||
title: "Contact Us",
|
||||
title: "Contact",
|
||||
},
|
||||
component: () => import("@/views/Contact.vue"),
|
||||
},
|
||||
|
||||
17
resources/js/store/UserStore.d.ts
vendored
17
resources/js/store/UserStore.d.ts
vendored
@@ -1,17 +0,0 @@
|
||||
import "pinia";
|
||||
import { UserDetails } from "./UserStore";
|
||||
|
||||
declare module "pinia" {
|
||||
export interface PiniaCustomProperties {
|
||||
setUserDetails(user: UserDetails): void;
|
||||
|
||||
id: string;
|
||||
token: string;
|
||||
username: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
permissions: string[];
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { defineStore, DefineStoreOptions } from "pinia";
|
||||
|
||||
export interface UserDetails {
|
||||
id: string;
|
||||
@@ -21,7 +21,7 @@ export interface UserState {
|
||||
permissions: string[];
|
||||
}
|
||||
|
||||
export const useUserStore = defineStore<string, UserState>({
|
||||
export const useUserStore = defineStore({
|
||||
id: "user",
|
||||
state: (): UserState => ({
|
||||
id: "",
|
||||
@@ -62,4 +62,4 @@ export const useUserStore = defineStore<string, UserState>({
|
||||
},
|
||||
|
||||
persist: true,
|
||||
});
|
||||
} as DefineStoreOptions<string, unknown, unknown, unknown> & { persist?: boolean });
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div>About</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -60,7 +60,7 @@
|
||||
<template v-else>
|
||||
<h1>Message Sent!</h1>
|
||||
<p class="text-center">
|
||||
Your message as been sent to us. We will respond
|
||||
Your message as been sent.<br />We will respond
|
||||
as soon as we can.
|
||||
</p>
|
||||
<SMButton
|
||||
@@ -76,22 +76,20 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue";
|
||||
import { useReCaptcha } from "vue-recaptcha-v3";
|
||||
import SMButton from "../components/SMButton.vue";
|
||||
import SMDialog from "../components/SMDialog.vue";
|
||||
import SMForm from "../components/SMForm.vue";
|
||||
import SMInput from "../components/SMInput.vue";
|
||||
|
||||
import { api } from "../helpers/api";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Email, Min, Required } from "../helpers/validate";
|
||||
|
||||
import { reactive, ref } from "vue";
|
||||
import { useReCaptcha } from "vue-recaptcha-v3";
|
||||
|
||||
const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();
|
||||
const form = reactive(
|
||||
Form({
|
||||
name: FormControl("", And([Required(), Min(4)])),
|
||||
name: FormControl("", And([Required()])),
|
||||
email: FormControl("", And([Required(), Email()])),
|
||||
content: FormControl("", And([Required(), Min(8)])),
|
||||
})
|
||||
@@ -108,20 +106,19 @@ const handleSubmit = async () => {
|
||||
await api.post({
|
||||
url: "/contact",
|
||||
body: {
|
||||
name: form.name.value,
|
||||
email: form.email.value,
|
||||
name: form.controls.name.value,
|
||||
email: form.controls.email.value,
|
||||
captcha_token: captcha,
|
||||
content: form.content.value,
|
||||
content: form.controls.content.value,
|
||||
},
|
||||
});
|
||||
|
||||
formSubmitted.value = true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
form.apiErrors(err);
|
||||
} catch (error) {
|
||||
form.error("A captcha error occurred. Try reloading the page.");
|
||||
} finally {
|
||||
form.loading(false);
|
||||
}
|
||||
|
||||
form.loading(false);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<template>
|
||||
<div ref="root" :class="classes">
|
||||
<div class="mdialog">
|
||||
<button @click="confimer">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { transitionEnter, transitionLeave } from "../helpers/transition";
|
||||
|
||||
const root = ref(null);
|
||||
const classes = ref(["mdialog-mask", "fade-enter-from"]);
|
||||
|
||||
const props = defineProps({ title: "" });
|
||||
let data = {
|
||||
title: props.title,
|
||||
};
|
||||
|
||||
const emit = defineEmits(["confirm", "cancel"]);
|
||||
|
||||
const confimer = () => {
|
||||
transitionLeave(root, "fade", () => {
|
||||
emit("confirm", {});
|
||||
});
|
||||
};
|
||||
|
||||
transitionEnter(root, "fade");
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.mdialog-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 2000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mdialog {
|
||||
padding: 1rem 2rem;
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
@@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<SMDialog>
|
||||
<SMButton type="primary" label="Confirm" @click="onClick" />
|
||||
</SMDialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import SMDialog from "./Dialog.vue";
|
||||
import SMButton from "../components/SMButton.vue";
|
||||
|
||||
const emit = defineEmits(["confirm", "cancel"]);
|
||||
|
||||
const onClick = () => {
|
||||
console.log("click");
|
||||
emit("confirm");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
@@ -48,7 +48,6 @@ import SMDialog from "../components/SMDialog.vue";
|
||||
import SMForm from "../components/SMForm.vue";
|
||||
import SMFormFooter from "../components/SMFormFooter.vue";
|
||||
import SMInput from "../components/SMInput.vue";
|
||||
|
||||
import { api } from "../helpers/api";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Max, Min, Required } from "../helpers/validate";
|
||||
@@ -71,21 +70,30 @@ const handleSubmit = async () => {
|
||||
await api.post({
|
||||
url: "/users/verifyEmail",
|
||||
body: {
|
||||
code: form.code.value,
|
||||
code: form.controls.code.value,
|
||||
captcha_token: captcha,
|
||||
},
|
||||
});
|
||||
|
||||
formDone.value = true;
|
||||
} catch (err) {
|
||||
form.apiErrors(err);
|
||||
} catch (error) {
|
||||
form.apiErrors(error);
|
||||
} finally {
|
||||
form.loading(false);
|
||||
}
|
||||
|
||||
form.loading(false);
|
||||
};
|
||||
|
||||
if (useRoute().query.code !== undefined) {
|
||||
form.code.value = useRoute().query.code;
|
||||
const code = useRoute().query.code;
|
||||
|
||||
if (Array.isArray(code)) {
|
||||
if (code.length > 0) {
|
||||
form.controls.code.value = code[0];
|
||||
}
|
||||
} else {
|
||||
form.controls.code.value = code;
|
||||
}
|
||||
|
||||
handleSubmit();
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
<template>
|
||||
<SMContainer class="dashboard mx-auto workshops">
|
||||
<h1>Workshops</h1>
|
||||
<SMMessage
|
||||
v-if="formMessage.message"
|
||||
:icon="formMessage.icon"
|
||||
:type="formMessage.type"
|
||||
:message="formMessage.message"
|
||||
class="mt-5" />
|
||||
<SMPanelList>
|
||||
<SMPanel
|
||||
v-for="event in events.value"
|
||||
:key="event.id"
|
||||
:to="{ name: 'event', params: { slug: event.id } }"
|
||||
:title="event.title"
|
||||
:date="event.start_at"></SMPanel>
|
||||
</SMPanelList>
|
||||
</SMContainer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import SMMessage from "../components/SMMessage.vue";
|
||||
import SMPanelList from "../components/SMPanelList.vue";
|
||||
import SMPanel from "../components/SMPanel.vue";
|
||||
import { reactive } from "vue";
|
||||
import { api } from "../helpers/api";
|
||||
|
||||
const events = reactive([]);
|
||||
|
||||
const formMessage = reactive({
|
||||
icon: "",
|
||||
type: "",
|
||||
message: "",
|
||||
});
|
||||
|
||||
const handleLoad = async () => {
|
||||
formMessage.type = "error";
|
||||
formMessage.icon = "alert-circle-outline";
|
||||
formMessage.message = "";
|
||||
|
||||
try {
|
||||
let result = await api.get({
|
||||
url: "/events",
|
||||
params: {
|
||||
limit: 10,
|
||||
},
|
||||
});
|
||||
events.value = result.json.events;
|
||||
} catch (error) {
|
||||
formMessage.message =
|
||||
error.json?.message || "Could not load any events from the server.";
|
||||
}
|
||||
};
|
||||
|
||||
handleLoad();
|
||||
</script>
|
||||
@@ -45,14 +45,13 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue";
|
||||
import { useReCaptcha } from "vue-recaptcha-v3";
|
||||
import { api } from "../helpers/api";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Min, Required } from "../helpers/validate";
|
||||
|
||||
import SMButton from "../components/SMButton.vue";
|
||||
import SMDialog from "../components/SMDialog.vue";
|
||||
import SMFormFooter from "../components/SMFormFooter.vue";
|
||||
import SMInput from "../components/SMInput.vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Min, Required } from "../helpers/validate";
|
||||
|
||||
const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();
|
||||
const formDone = ref(false);
|
||||
@@ -72,7 +71,7 @@ const handleSubmit = async () => {
|
||||
await api.post({
|
||||
url: "/users/forgotPassword",
|
||||
body: {
|
||||
username: form.username.value,
|
||||
username: form.controls.username.value,
|
||||
captcha_token: captcha,
|
||||
},
|
||||
});
|
||||
@@ -84,8 +83,8 @@ const handleSubmit = async () => {
|
||||
} else {
|
||||
form.apiErrors(error);
|
||||
}
|
||||
} finally {
|
||||
form.loading(false);
|
||||
}
|
||||
|
||||
form.loading(false);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -43,17 +43,15 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Email, Required } from "../helpers/validate";
|
||||
|
||||
import { useReCaptcha } from "vue-recaptcha-v3";
|
||||
import SMButton from "../components/SMButton.vue";
|
||||
import SMDialog from "../components/SMDialog.vue";
|
||||
import SMForm from "../components/SMForm.vue";
|
||||
import SMFormFooter from "../components/SMFormFooter.vue";
|
||||
import SMInput from "../components/SMInput.vue";
|
||||
|
||||
import { useReCaptcha } from "vue-recaptcha-v3";
|
||||
import { api } from "../helpers/api";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Email, Required } from "../helpers/validate";
|
||||
|
||||
const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();
|
||||
const formDone = ref(false);
|
||||
@@ -73,7 +71,7 @@ const handleSubmit = async () => {
|
||||
await api.post({
|
||||
url: "/users/forgotUsername",
|
||||
body: {
|
||||
email: form.email.value,
|
||||
email: form.controls.email.value,
|
||||
captcha_token: captcha,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div>Home</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
@@ -40,8 +40,8 @@ import SMDialog from "../components/SMDialog.vue";
|
||||
import SMForm from "../components/SMForm.vue";
|
||||
import SMFormFooter from "../components/SMFormFooter.vue";
|
||||
import SMInput from "../components/SMInput.vue";
|
||||
|
||||
import { api } from "../helpers/api";
|
||||
import { LoginResponse } from "../helpers/api.types";
|
||||
import { Form, FormControl } from "../helpers/form";
|
||||
import { And, Min, Required } from "../helpers/validate";
|
||||
import { useUserStore } from "../store/UserStore";
|
||||
@@ -55,39 +55,39 @@ const form = reactive(
|
||||
})
|
||||
);
|
||||
|
||||
const redirect = useRoute().query.redirect;
|
||||
const redirectQuery = useRoute().query.redirect;
|
||||
|
||||
const handleSubmit = async () => {
|
||||
form.message();
|
||||
form.loading(true);
|
||||
|
||||
try {
|
||||
let res = await api.post({
|
||||
let result = await api.post({
|
||||
url: "/login",
|
||||
body: {
|
||||
username: form.username.value,
|
||||
password: form.password.value,
|
||||
username: form.controls.username.value,
|
||||
password: form.controls.password.value,
|
||||
},
|
||||
});
|
||||
|
||||
userStore.setUserDetails(res.data.user);
|
||||
userStore.setUserToken(res.data.token);
|
||||
if (redirect !== undefined) {
|
||||
if (redirect.startsWith("api/")) {
|
||||
window.location.href =
|
||||
redirect + "?token=" + encodeURIComponent(res.data.token);
|
||||
} else {
|
||||
router.push({ path: redirect });
|
||||
}
|
||||
const login = result.data as unknown as LoginResponse;
|
||||
|
||||
userStore.setUserDetails(login.user);
|
||||
userStore.setUserToken(login.token);
|
||||
if (redirectQuery !== undefined) {
|
||||
const redirect = Array.isArray(redirectQuery)
|
||||
? redirectQuery[0]
|
||||
: redirectQuery;
|
||||
|
||||
router.push({ path: redirect });
|
||||
} else {
|
||||
router.push({ name: "dashboard" });
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
form.apiErrors(err);
|
||||
} finally {
|
||||
form.loading(false);
|
||||
}
|
||||
|
||||
form.loading(false);
|
||||
};
|
||||
|
||||
if (userStore.token) {
|
||||
|
||||
Reference in New Issue
Block a user