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

1
.gitignore vendored
View File

@@ -1,6 +1,5 @@
/.phpunit.cache
/node_modules
/public/build
/public/hot
/public/storage
/storage/*.key

View File

@@ -8,10 +8,8 @@
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Kalnoy\Nestedset\NodeTrait;
use Illuminate\Support\Str;
use Kalnoy\Nestedset\NodeTrait;
/**
* Class Category
@@ -25,8 +23,6 @@
* @property int $_lft
* @property int $_rgt
* @property int|null $parent_id
*
* @package App\Models
*/
class Category extends Model
{
@@ -38,7 +34,7 @@ class Category extends Model
'enabled' => 'bool',
'_lft' => 'int',
'_rgt' => 'int',
'parent_id' => 'int'
'parent_id' => 'int',
];
protected $fillable = [
@@ -47,7 +43,7 @@ class Category extends Model
'enabled',
'_lft',
'_rgt',
'parent_id'
'parent_id',
];
protected static function boot()
@@ -68,6 +64,4 @@ public function saveQuietly(array $options = [])
return $this->save($options);
});
}
}

View File

@@ -12,7 +12,8 @@
"laravel/framework": "^10.10",
"laravel/sanctum": "^3.2",
"laravel/tinker": "^2.8",
"spatie/laravel-googletagmanager": "^2.6"
"spatie/laravel-googletagmanager": "^2.6",
"tightenco/ziggy": "^1.6"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",

69
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c15e60f5acf3cb829ee1ea5a9cf4432c",
"content-hash": "d34b77923c789e17f7e8a9c58c191ebb",
"packages": [
{
"name": "artesaos/seotools",
@@ -5550,6 +5550,73 @@
],
"time": "2023-08-24T14:51:05+00:00"
},
{
"name": "tightenco/ziggy",
"version": "v1.6.2",
"source": {
"type": "git",
"url": "https://github.com/tighten/ziggy.git",
"reference": "41eb6384a9f9ae85cf54d6dc8f98dab282b07890"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tighten/ziggy/zipball/41eb6384a9f9ae85cf54d6dc8f98dab282b07890",
"reference": "41eb6384a9f9ae85cf54d6dc8f98dab282b07890",
"shasum": ""
},
"require": {
"ext-json": "*",
"laravel/framework": ">=5.4@dev"
},
"require-dev": {
"orchestra/testbench": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0",
"phpunit/phpunit": "^6.0 || ^7.0 || ^8.0 || ^9.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Tightenco\\Ziggy\\ZiggyServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Tightenco\\Ziggy\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Coulbourne",
"email": "daniel@tighten.co"
},
{
"name": "Jake Bathman",
"email": "jake@tighten.co"
},
{
"name": "Jacob Baker-Kretzmar",
"email": "jacob@tighten.co"
}
],
"description": "Generates a Blade directive exporting all of your named Laravel routes. Also provides a nice route() helper function in JavaScript.",
"homepage": "https://github.com/tighten/ziggy",
"keywords": [
"Ziggy",
"javascript",
"laravel",
"routes"
],
"support": {
"issues": "https://github.com/tighten/ziggy/issues",
"source": "https://github.com/tighten/ziggy/tree/v1.6.2"
},
"time": "2023-08-18T20:28:21+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
"version": "2.2.6",

View File

@@ -493,18 +493,18 @@
|
*/
// 'connections' => [
// 'read_only_external' => [
// 'parent' => \App\Models\ReadOnlyModel::class,
// 'connection' => true,
// 'users' => [
// 'connection' => false,
// ],
// 'my_other_database' => [
// 'password_resets' => [
// 'connection' => false,
// ]
// ]
// ],
// ],
// 'connections' => [
// 'read_only_external' => [
// 'parent' => \App\Models\ReadOnlyModel::class,
// 'connection' => true,
// 'users' => [
// 'connection' => false,
// ],
// 'my_other_database' => [
// 'password_resets' => [
// 'connection' => false,
// ]
// ]
// ],
// ],
];

View File

@@ -9,7 +9,7 @@
* The default configurations to be used by the meta generator.
*/
'defaults' => [
'title' => "EchoScoop: Bite-sized world news", // set false to total remove
'title' => 'EchoScoop: Bite-sized world news', // set false to total remove
'titleBefore' => false, // Put defaults.title before page title, like 'It's Over 9000! - Dashboard'
'description' => 'Distilling world news into bite-sized scoops.', // set false to total remove
'separator' => ' - ',

View File

@@ -2,10 +2,8 @@
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Category;
use Illuminate\Database\Seeder;
class CategorySeeder extends Seeder
{
@@ -23,8 +21,8 @@ public function run(): void
['name' => 'Information Technology'],
['name' => 'Marketing'],
['name' => 'Office'],
['name' => 'Telecommunications']
]
['name' => 'Telecommunications'],
],
],
[
'name' => 'Entertainment',
@@ -33,8 +31,8 @@ public function run(): void
['name' => 'Film & Television'],
['name' => 'Games & Toys'],
['name' => 'Music and Video'],
['name' => 'Adult Entertainment']
]
['name' => 'Adult Entertainment'],
],
],
['name' => 'Food & Drink'],
[
@@ -43,14 +41,14 @@ public function run(): void
['name' => 'Collectibles'],
['name' => 'Pets'],
['name' => 'Photography'],
['name' => 'Hunting & Fishing']
]
['name' => 'Hunting & Fishing'],
],
],
[
'name' => 'Education',
'children' => [
['name' => 'Languages']
]
['name' => 'Languages'],
],
],
['name' => 'Law'],
['name' => 'Politics'],
@@ -59,14 +57,14 @@ public function run(): void
'children' => [
['name' => 'Home & Garden'],
['name' => 'Clothing & Accessories'],
['name' => 'Computer & Electronics']
]
['name' => 'Computer & Electronics'],
],
],
[
'name' => 'Religion & Spirituality',
'children' => [
['name' => 'Holistic Health']
]
['name' => 'Holistic Health'],
],
],
['name' => 'Real Estate'],
['name' => 'Social Networks'],
@@ -75,39 +73,35 @@ public function run(): void
'children' => [
['name' => 'Family'],
['name' => 'Wedding'],
['name' => 'Immigration']
]
['name' => 'Immigration'],
],
],
[
'name' => 'Wellness',
'children' => [
['name' => 'Health & Beauty'],
['name' => 'Psychology & Psychotherapy']
]
['name' => 'Psychology & Psychotherapy'],
],
],
[
'name' => 'Tips & Tricks',
'children' => [
['name' => 'How to']
]
['name' => 'How to'],
],
],
[
'name' => 'Travel',
'children' => [
['name' => 'Holiday'],
['name' => 'World Festivals'],
['name' => 'Outdoors']
]
['name' => 'Outdoors'],
],
],
];
foreach ($categories as $category)
{
foreach ($categories as $category) {
$node = Category::create($category);
}
}
}

1468
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,20 +2,30 @@
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
"dev": "vite --debug",
"build": "vite build --debug"
},
"devDependencies": {
"axios": "^1.1.2",
"@vitejs/plugin-vue": "^4.3.4",
"axios": "^1.5.0",
"laravel-vite-plugin": "^0.8.0",
"path": "^0.12.7",
"sass": "^1.68.0",
"unplugin-vue-components": "^0.25.2",
"vite": "^4.0.0",
"vite-plugin-compression": "^0.5.1"
},
"dependencies": {
"bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.1",
"js-cookie": "^3.0.5"
"js-cookie": "^3.0.5",
"mitt": "^3.0.1",
"pinia": "^2.1.6",
"vue": "^3.3.4",
"vue-axios": "^3.5.2",
"vue-loader": "^17.2.2",
"vue-router": "^4.2.4",
"vue3-toastify": "^0.1.13",
"ziggy-js": "^1.6.2"
}
}

View File

@@ -3,7 +3,7 @@
# eval 'php artisan optimize:clear';
# eval 'php artisan responsecache:clear';
# eval 'php artisan opcache:clear';
# eval 'APP_URL=https://echoscoop.com php artisan ziggy:generate';
eval 'APP_URL=https://echoscoop.com php artisan ziggy:generate';
eval 'blade-formatter --write resources/**/*.blade.php';
eval './vendor/bin/pint';
eval 'npm run build';

View File

@@ -0,0 +1 @@
import{_ as o,o as p,c,a as r,b as u,p as i,d as m,e as g,f as _,g as d,v as f,Z as n,h as l}from"./vue-a36422cb.js";const A={name:"AppAuth"};function $(s,a,t,Z,w,x){return p(),c("div")}const h=o(A,[["render",$]]),e=r({AppAuth:h}),v=Object.assign({});e.use(u());e.use(i,m);e.use(g);e.use(_);e.use(d);e.use(f.ZiggyVue,n);window.Ziggy=n;Object.entries({...v}).forEach(([s,a])=>{const t=s.split("/").pop().replace(/\.\w+$/,"").replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();e.component(t,l(a))});e.mount("#app");

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1,46 @@
{
"_vue-a36422cb.js": {
"css": [
"assets/vue-935fc652.css"
],
"file": "assets/vue-a36422cb.js"
},
"node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff": {
"file": "assets/bootstrap-icons-4d4572ef.woff",
"src": "node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff"
},
"node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff2": {
"file": "assets/bootstrap-icons-bacd70af.woff2",
"src": "node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff2"
},
"resources/js/app-auth.js": {
"file": "assets/app-auth-34561e68.js",
"imports": [
"_vue-a36422cb.js"
],
"isEntry": true,
"src": "resources/js/app-auth.js"
},
"resources/js/app-front.js": {
"file": "assets/app-front-948dc8d8.js",
"imports": [
"_vue-a36422cb.js"
],
"isEntry": true,
"src": "resources/js/app-front.js"
},
"resources/sass/app-auth.scss": {
"file": "assets/app-front-d32494d2.css",
"isEntry": true,
"src": "resources/sass/app-auth.scss"
},
"resources/sass/app-front.scss": {
"file": "assets/app-front-d32494d2.css",
"isEntry": true,
"src": "resources/sass/app-auth.scss"
},
"vue.css": {
"file": "assets/vue-935fc652.css",
"src": "vue.css"
}
}

Binary file not shown.

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,8 @@
import { defineConfig } from "vite";
import laravel from "laravel-vite-plugin";
import vue from "@vitejs/plugin-vue";
import path from "path";
import Components from "unplugin-vue-components/vite";
import viteCompression from "vite-plugin-compression";
export default defineConfig(({ mode }) => {
@@ -10,17 +12,31 @@ export default defineConfig(({ mode }) => {
},
plugins: [
viteCompression(),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
laravel({
input: [
"resources/sass/app-front.scss",
"resources/js/app-front.js",
,
"resources/sass/app-auth.scss",
"resources/js/app-auth.js",
],
refresh: true,
}),
Components({
dirs: ["resources/js/vue"],
dts: false,
}),
],
resolve: {
alias: {
vue: "vue/dist/vue.esm-bundler.js",
"@": path.resolve(__dirname, "./resources/js"),
"~": path.resolve(__dirname, "node_modules"),
"~bootstrap": path.resolve(__dirname, "node_modules/bootstrap"),