Add (vite build)

This commit is contained in:
2023-09-21 23:58:23 +08:00
parent d8ed8bdb1d
commit 18705bd5e4
39 changed files with 3686 additions and 1221 deletions

View File

View File

@@ -1,3 +0,0 @@
.abc {
color: "#000";
}

622
resources/css/toastify.css Normal file
View File

@@ -0,0 +1,622 @@
:root {
--toastify-color-light: #fff;
--toastify-color-dark: #121212;
--toastify-color-info: #3498db;
--toastify-color-success: #07bc0c;
--toastify-color-warning: #f1c40f;
--toastify-color-error: #e74c3c;
--toastify-color-transparent: #ffffffb3;
--toastify-icon-color-info: var(--toastify-color-info);
--toastify-icon-color-success: var(--toastify-color-success);
--toastify-icon-color-warning: var(--toastify-color-warning);
--toastify-icon-color-error: var(--toastify-color-error);
--toastify-toast-width: 320px;
--toastify-toast-background: #fff;
--toastify-toast-min-height: 64px;
--toastify-toast-max-height: 800px;
--toastify-font-family: inherit;
--toastify-z-index: 9999;
--toastify-text-color-light: #757575;
--toastify-text-color-dark: #fff;
--toastify-text-color-info: #fff;
--toastify-text-color-success: #fff;
--toastify-text-color-warning: #fff;
--toastify-text-color-error: #fff;
--toastify-spinner-color: #616161;
--toastify-spinner-color-empty-area: #e0e0e0;
--toastify-color-progress-light: linear-gradient(
90deg,
#4cd964,
#5ac8fa,
#007aff,
#34aadc,
#5856d6,
#ff2d55
);
--toastify-color-progress-dark: #bb86fc;
--toastify-color-progress-info: var(--toastify-color-info);
--toastify-color-progress-success: var(--toastify-color-success);
--toastify-color-progress-warning: var(--toastify-color-warning);
--toastify-color-progress-error: var(--toastify-color-error);
--toastify-color-progress-colored: #ddd;
}
.Toastify__toast-container {
box-sizing: border-box;
color: #fff;
padding: 4px;
position: fixed;
transform: translate3d(0, 0, var(--toastify-z-index) px);
width: var(--toastify-toast-width);
z-index: var(--toastify-z-index);
}
.Toastify__toast-container--top-left {
left: 1em;
top: 1em;
}
.Toastify__toast-container--top-center {
left: 50%;
top: 1em;
transform: translateX(-50%);
}
.Toastify__toast-container--top-right {
right: 1em;
top: 1em;
}
.Toastify__toast-container--bottom-left {
bottom: 1em;
left: 1em;
}
.Toastify__toast-container--bottom-center {
bottom: 1em;
left: 50%;
transform: translateX(-50%);
}
.Toastify__toast-container--bottom-right {
bottom: 1em;
right: 1em;
}
@media only screen and (max-width: 480px) {
.Toastify__toast-container {
left: 0;
margin: 0;
padding: 0;
width: 100vw;
}
.Toastify__toast-container--top-center,
.Toastify__toast-container--top-left,
.Toastify__toast-container--top-right {
top: 0;
transform: translateX(0);
}
.Toastify__toast-container--bottom-center,
.Toastify__toast-container--bottom-left,
.Toastify__toast-container--bottom-right {
bottom: 0;
transform: translateX(0);
}
.Toastify__toast-container--rtl {
left: auto;
right: 0;
}
}
.Toastify__toast {
border-radius: 4px;
box-shadow: 0 1px 10px 0 #0000001a, 0 2px 15px 0 #0000000d;
box-sizing: border-box;
cursor: pointer;
direction: ltr;
display: flex;
font-family: var(--toastify-font-family);
justify-content: space-between;
margin-bottom: 1rem;
max-height: var(--toastify-toast-max-height);
min-height: var(--toastify-toast-min-height);
overflow: hidden;
padding: 8px;
position: relative;
z-index: 0;
}
.Toastify__toast--rtl {
direction: rtl;
}
.Toastify__toast-body {
align-items: center;
display: flex;
flex: 1 1 auto;
margin: auto 0;
padding: 6px;
white-space: pre-wrap;
}
.Toastify__toast-body > div:last-child {
flex: 1;
}
.Toastify__toast-icon {
display: flex;
flex-shrink: 0;
margin-inline-end: 10px;
width: 20px;
}
.Toastify--animate {
animation-duration: 0.7s;
animation-fill-mode: both;
}
.Toastify--animate-icon {
animation-duration: 0.3s;
animation-fill-mode: both;
}
@media only screen and (max-width: 480px) {
.Toastify__toast {
border-radius: 0;
margin-bottom: 0;
}
}
.Toastify__toast-theme--dark {
background: var(--toastify-color-dark);
color: var(--toastify-text-color-dark);
}
.Toastify__toast-theme--colored.Toastify__toast--default,
.Toastify__toast-theme--light {
background: var(--toastify-color-light);
color: var(--toastify-text-color-light);
}
.Toastify__toast-theme--colored.Toastify__toast--info {
background: var(--toastify-color-info);
color: var(--toastify-text-color-info);
}
.Toastify__toast-theme--colored.Toastify__toast--success {
background: var(--toastify-color-success);
color: var(--toastify-text-color-success);
}
.Toastify__toast-theme--colored.Toastify__toast--warning {
background: var(--toastify-color-warning);
color: var(--toastify-text-color-warning);
}
.Toastify__toast-theme--colored.Toastify__toast--error {
background: var(--toastify-color-error);
color: var(--toastify-text-color-error);
}
.Toastify__progress-bar-theme--light {
background: var(--toastify-color-progress-light);
}
.Toastify__progress-bar-theme--dark {
background: var(--toastify-color-progress-dark);
}
.Toastify__progress-bar--info {
background: var(--toastify-color-progress-info);
}
.Toastify__progress-bar--success {
background: var(--toastify-color-progress-success);
}
.Toastify__progress-bar--warning {
background: var(--toastify-color-progress-warning);
}
.Toastify__progress-bar--error {
background: var(--toastify-color-progress-error);
}
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--default {
background: var(--toastify-color-progress-colored);
}
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--error,
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--info,
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--success,
.Toastify__progress-bar-theme--colored.Toastify__progress-bar--warning {
background: var(--toastify-color-transparent);
}
.Toastify__close-button {
align-self: flex-start;
background: #0000;
border: none;
color: #fff;
cursor: pointer;
opacity: 0.7;
outline: none;
padding: 0;
transition: 0.3s ease;
}
.Toastify__close-button--light {
color: #000;
opacity: 0.3;
}
.Toastify__close-button > svg {
fill: currentcolor;
height: 16px;
width: 14px;
}
.Toastify__close-button:focus,
.Toastify__close-button:hover {
opacity: 1;
}
@keyframes Toastify__trackProgress {
0% {
transform: scaleX(1);
}
to {
transform: scaleX(0);
}
}
.Toastify__progress-bar {
bottom: 0;
height: 5px;
left: 0;
opacity: 0.7;
position: absolute;
transform-origin: left;
width: 100%;
z-index: var(--toastify-z-index);
}
.Toastify__progress-bar--animated {
animation: Toastify__trackProgress linear 1 forwards;
}
.Toastify__progress-bar--controlled {
transition: transform 0.2s;
}
.Toastify__progress-bar--rtl {
left: auto;
right: 0;
transform-origin: right;
}
.Toastify__spinner {
animation: Toastify__spin 0.65s linear infinite;
border: 2px solid;
border-color: var(--toastify-spinner-color-empty-area);
border-radius: 100%;
border-right-color: var(--toastify-spinner-color);
box-sizing: border-box;
height: 20px;
width: 20px;
}
@keyframes Toastify__bounceInRight {
0%,
60%,
75%,
90%,
to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
transform: translate3d(3000px, 0, 0);
}
60% {
opacity: 1;
transform: translate3d(-25px, 0, 0);
}
75% {
transform: translate3d(10px, 0, 0);
}
90% {
transform: translate3d(-5px, 0, 0);
}
to {
transform: none;
}
}
@keyframes Toastify__bounceOutRight {
20% {
opacity: 1;
transform: translate3d(-20px, 0, 0);
}
to {
opacity: 0;
transform: translate3d(2000px, 0, 0);
}
}
@keyframes Toastify__bounceInLeft {
0%,
60%,
75%,
90%,
to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
transform: translate3d(-3000px, 0, 0);
}
60% {
opacity: 1;
transform: translate3d(25px, 0, 0);
}
75% {
transform: translate3d(-10px, 0, 0);
}
90% {
transform: translate3d(5px, 0, 0);
}
to {
transform: none;
}
}
@keyframes Toastify__bounceOutLeft {
20% {
opacity: 1;
transform: translate3d(20px, 0, 0);
}
to {
opacity: 0;
transform: translate3d(-2000px, 0, 0);
}
}
@keyframes Toastify__bounceInUp {
0%,
60%,
75%,
90%,
to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
transform: translate3d(0, 3000px, 0);
}
60% {
opacity: 1;
transform: translate3d(0, -20px, 0);
}
75% {
transform: translate3d(0, 10px, 0);
}
90% {
transform: translate3d(0, -5px, 0);
}
to {
transform: translateZ(0);
}
}
@keyframes Toastify__bounceOutUp {
20% {
transform: translate3d(0, -10px, 0);
}
40%,
45% {
opacity: 1;
transform: translate3d(0, 20px, 0);
}
to {
opacity: 0;
transform: translate3d(0, -2000px, 0);
}
}
@keyframes Toastify__bounceInDown {
0%,
60%,
75%,
90%,
to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: 0;
transform: translate3d(0, -3000px, 0);
}
60% {
opacity: 1;
transform: translate3d(0, 25px, 0);
}
75% {
transform: translate3d(0, -10px, 0);
}
90% {
transform: translate3d(0, 5px, 0);
}
to {
transform: none;
}
}
@keyframes Toastify__bounceOutDown {
20% {
transform: translate3d(0, 10px, 0);
}
40%,
45% {
opacity: 1;
transform: translate3d(0, -20px, 0);
}
to {
opacity: 0;
transform: translate3d(0, 2000px, 0);
}
}
.Toastify__bounce-enter--bottom-left,
.Toastify__bounce-enter--top-left {
animation-name: Toastify__bounceInLeft;
}
.Toastify__bounce-enter--bottom-right,
.Toastify__bounce-enter--top-right {
animation-name: Toastify__bounceInRight;
}
.Toastify__bounce-enter--top-center {
animation-name: Toastify__bounceInDown;
}
.Toastify__bounce-enter--bottom-center {
animation-name: Toastify__bounceInUp;
}
.Toastify__bounce-exit--bottom-left,
.Toastify__bounce-exit--top-left {
animation-name: Toastify__bounceOutLeft;
}
.Toastify__bounce-exit--bottom-right,
.Toastify__bounce-exit--top-right {
animation-name: Toastify__bounceOutRight;
}
.Toastify__bounce-exit--top-center {
animation-name: Toastify__bounceOutUp;
}
.Toastify__bounce-exit--bottom-center {
animation-name: Toastify__bounceOutDown;
}
@keyframes Toastify__zoomIn {
0% {
opacity: 0;
transform: scale3d(0.3, 0.3, 0.3);
}
50% {
opacity: 1;
}
}
@keyframes Toastify__zoomOut {
0% {
opacity: 1;
}
50% {
opacity: 0;
transform: scale3d(0.3, 0.3, 0.3);
}
to {
opacity: 0;
}
}
.Toastify__zoom-enter {
animation-name: Toastify__zoomIn;
}
.Toastify__zoom-exit {
animation-name: Toastify__zoomOut;
}
@keyframes Toastify__flipIn {
0% {
animation-timing-function: ease-in;
opacity: 0;
transform: perspective(400px) rotateX(90deg);
}
40% {
animation-timing-function: ease-in;
transform: perspective(400px) rotateX(-20deg);
}
60% {
opacity: 1;
transform: perspective(400px) rotateX(10deg);
}
80% {
transform: perspective(400px) rotateX(-5deg);
}
to {
transform: perspective(400px);
}
}
@keyframes Toastify__flipOut {
0% {
transform: perspective(400px);
}
30% {
opacity: 1;
transform: perspective(400px) rotateX(-20deg);
}
to {
opacity: 0;
transform: perspective(400px) rotateX(90deg);
}
}
.Toastify__flip-enter {
animation-name: Toastify__flipIn;
}
.Toastify__flip-exit {
animation-name: Toastify__flipOut;
}
@keyframes Toastify__slideInRight {
0% {
transform: translate3d(110%, 0, 0);
visibility: visible;
}
to {
transform: translateZ(0);
}
}
@keyframes Toastify__slideInLeft {
0% {
transform: translate3d(-110%, 0, 0);
visibility: visible;
}
to {
transform: translateZ(0);
}
}
@keyframes Toastify__slideInUp {
0% {
transform: translate3d(0, 110%, 0);
visibility: visible;
}
to {
transform: translateZ(0);
}
}
@keyframes Toastify__slideInDown {
0% {
transform: translate3d(0, -110%, 0);
visibility: visible;
}
to {
transform: translateZ(0);
}
}
@keyframes Toastify__slideOutRight {
0% {
transform: translateZ(0);
}
to {
transform: translate3d(110%, 0, 0);
visibility: hidden;
}
}
@keyframes Toastify__slideOutLeft {
0% {
transform: translateZ(0);
}
to {
transform: translate3d(-110%, 0, 0);
visibility: hidden;
}
}
@keyframes Toastify__slideOutDown {
0% {
transform: translateZ(0);
}
to {
transform: translate3d(0, 500px, 0);
visibility: hidden;
}
}
@keyframes Toastify__slideOutUp {
0% {
transform: translateZ(0);
}
to {
transform: translate3d(0, -500px, 0);
visibility: hidden;
}
}
.Toastify__slide-enter--bottom-left,
.Toastify__slide-enter--top-left {
animation-name: Toastify__slideInLeft;
}
.Toastify__slide-enter--bottom-right,
.Toastify__slide-enter--top-right {
animation-name: Toastify__slideInRight;
}
.Toastify__slide-enter--top-center {
animation-name: Toastify__slideInDown;
}
.Toastify__slide-enter--bottom-center {
animation-name: Toastify__slideInUp;
}
.Toastify__slide-exit--bottom-left,
.Toastify__slide-exit--top-left {
animation-name: Toastify__slideOutLeft;
}
.Toastify__slide-exit--bottom-right,
.Toastify__slide-exit--top-right {
animation-name: Toastify__slideOutRight;
}
.Toastify__slide-exit--top-center {
animation-name: Toastify__slideOutUp;
}
.Toastify__slide-exit--bottom-center {
animation-name: Toastify__slideOutDown;
}
@keyframes Toastify__spin {
0% {
transform: rotate(0deg);
}
to {
transform: rotate(1turn);
}
}

9
resources/js/AppAuth.vue Normal file
View File

@@ -0,0 +1,9 @@
<template>
<div></div>
</template>
<script>
export default {
name: "AppAuth",
};
</script>
<style></style>

View File

@@ -0,0 +1,9 @@
<template>
<div></div>
</template>
<script>
export default {
name: "AppFront",
};
</script>
<style></style>

51
resources/js/app-auth.js Normal file
View File

@@ -0,0 +1,51 @@
import { createApp, defineAsyncComponent } from "vue";
import AppAuth from "@/AppAuth.vue";
const app = createApp({ AppAuth });
const vueComponents = import.meta.glob("@/vue/auth/**/*.vue", {
eager: false,
});
import.meta.glob(["../images/**", "../fonts/**"]);
import { createPinia } from "pinia";
app.use(createPinia());
import axios from "./plugins/axios";
import VueAxios from "vue-axios";
app.use(VueAxios, axios);
import auth from "./plugins/auth";
app.use(auth);
import eventBus from "./plugins/event-bus";
app.use(eventBus);
import Vue3Toastify from "vue3-toastify";
import "../css/toastify.css";
app.use(Vue3Toastify);
import { Ziggy as ZiggyRoute } from "./ziggy";
import { ZiggyVue } from "ziggy-js/dist/vue";
app.use(ZiggyVue, ZiggyRoute);
window.Ziggy = ZiggyRoute;
Object.entries({ ...vueComponents }).forEach(([path, definition]) => {
// Get name of component, based on filename
// "./components/Fruits.vue" will become "Fruits"
const componentName = path
.split("/")
.pop()
.replace(/\.\w+$/, "")
.replace(/([a-z])([A-Z])/g, "$1-$2")
.toLowerCase();
// console.log(componentName);
// console.log(typeof definition);
// Register component on this Vue instance
app.component(componentName, defineAsyncComponent(definition));
});
app.mount("#app");

View File

@@ -1 +1,53 @@
import * as bootstrap from "~bootstrap";
import { createApp, defineAsyncComponent } from "vue";
import AppFront from "@/AppFront.vue";
const app = createApp({ AppFront });
const vueComponents = import.meta.glob("@/vue/front/**/*.vue", {
eager: false,
});
import.meta.glob(["../images/**", "../fonts/**"]);
import { createPinia } from "pinia";
app.use(createPinia());
import axios from "./plugins/axios";
import VueAxios from "vue-axios";
app.use(VueAxios, axios);
import auth from "./plugins/auth";
app.use(auth);
import eventBus from "./plugins/event-bus";
app.use(eventBus);
import Vue3Toastify from "vue3-toastify";
import "../css/toastify.css";
app.use(Vue3Toastify);
import { Ziggy as ZiggyRoute } from "./ziggy";
import { ZiggyVue } from "ziggy-js/dist/vue";
app.use(ZiggyVue, ZiggyRoute);
window.Ziggy = ZiggyRoute;
Object.entries({ ...vueComponents }).forEach(([path, definition]) => {
// Get name of component, based on filename
// "./components/Fruits.vue" will become "Fruits"
const componentName = path
.split("/")
.pop()
.replace(/\.\w+$/, "")
.replace(/([a-z])([A-Z])/g, "$1-$2")
.toLowerCase();
// console.log(componentName);
// console.log(typeof definition);
// Register component on this Vue instance
app.component(componentName, defineAsyncComponent(definition));
});
app.mount("#app");

View File

@@ -0,0 +1,11 @@
import { useAuthStore } from "@/stores/useAuth";
export default {
install: ({ config }) => {
config.globalProperties.$auth = useAuthStore();
if (useAuthStore().loggedIn) {
useAuthStore().ftechUser();
}
},
};

View File

@@ -0,0 +1,71 @@
import { useErrorStore } from "../stores/useError";
import axios from "axios";
import Cookies from "js-cookie";
axios.defaults.headers.common["Authorization"] = localStorage.getItem("token");
axios.defaults.withCredentials = true;
axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
const setCSRFToken = () => {
return axios.get("/sanctum/csrf-cookie"); // resolves to '/api/csrf-cookie'.
};
// Add a request interceptor
axios.interceptors.request.use(
function (config) {
// Do something before request is sent
useErrorStore().$reset();
if (!Cookies.get("XSRF-TOKEN")) {
return setCSRFToken().then((response) => config);
}
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
},
);
// Add a response interceptor
axios.interceptors.response.use(
function (response) {
// console.warn("axios.interceptors.response");
// console.warn(response);
if (response?.data?.data?.csrf_token?.length > 0) {
Cookies.set("XSRF-TOKEN", response.data.data.csrf_token);
} else if (response?.data?.data?.token?.length > 0) {
Cookies.set("XSRF-TOKEN", response.data.data.csrf_token);
}
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
},
function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
switch (error.response.status) {
case 401:
localStorage.removeItem("token");
window.location.reload();
break;
case 403:
case 404:
console.error("404");
break;
case 422:
useErrorStore().$state = error.response.data;
break;
default:
console.log(error.response.data);
}
return Promise.reject(error);
},
);
export default axios;

View File

@@ -0,0 +1,7 @@
import mitt from "mitt";
export default {
install: (app, options) => {
app.config.globalProperties.$eventBus = mitt();
},
};

View File

@@ -0,0 +1,44 @@
import { defineStore } from "pinia";
import axios from "axios";
export const useAuthStore = defineStore("auth", {
state: () => ({
loggedIn: localStorage.getItem("token") ? true : false,
user: null,
}),
getters: {},
actions: {
async login(credentials) {
await axios.get("sanctum/csrf-cookie");
const response = (await axios.post("api/login", credentials)).data;
if (response) {
const token = `Bearer ${response.token}`;
localStorage.setItem("token", token);
axios.defaults.headers.common["Authorization"] = token;
await this.ftechUser();
}
},
async logout() {
const response = (await axios.post("api/logout")).data;
if (response) {
localStorage.removeItem("token");
this.$reset();
}
},
async ftechUser() {
this.user = (await axios.get("api/me")).data;
this.loggedIn = true;
},
},
});

View File

@@ -0,0 +1,8 @@
import { defineStore } from "pinia";
export const useErrorStore = defineStore("error", {
state: () => ({
message: null,
errors: {},
}),
});

7
resources/js/ziggy.js Normal file
View File

@@ -0,0 +1,7 @@
const Ziggy = {"url":"https:\/\/echoscoop.com","port":null,"defaults":{},"routes":{"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"ignition.healthCheck":{"uri":"_ignition\/health-check","methods":["GET","HEAD"]},"ignition.executeSolution":{"uri":"_ignition\/execute-solution","methods":["POST"]},"ignition.updateConfig":{"uri":"_ignition\/update-config","methods":["POST"]}}};
if (typeof window !== 'undefined' && typeof window.Ziggy !== 'undefined') {
Object.assign(Ziggy.routes, window.Ziggy.routes);
}
export { Ziggy };

View File

@@ -0,0 +1,7 @@
@import "variables";
@import "~bootstrap/scss/bootstrap";
@import "~/bootstrap-icons/font/bootstrap-icons.css";
@import "../css/app-auth.css";

View File

@@ -1,6 +1,6 @@
@extends('front.layouts.app')
@section('content')
<div class="container px-4 py-5 my-5 text-center">
<h1 class="fw-bolder">Coming soon.</h1>
<h1 class="fw-bolder">Coming soon.</h1>
</div>
@endsection