Compare commits
No commits in common. "20c844a98b62d4a4bde455765ba8b259919ace48" and "ae4b8a34496fc69fb9bb49c2fca60d66009fe88a" have entirely different histories.
20c844a98b
...
ae4b8a3449
@ -20,15 +20,10 @@ class DatabaseSeeder extends Seeder
|
|||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
User::factory()->create([
|
User::factory()->create([
|
||||||
'nama' => 'Owner',
|
'nama' => 'Test',
|
||||||
'role' => 'owner',
|
'role' => 'owner',
|
||||||
'password' => bcrypt('123123'),
|
'password' => bcrypt('123123'),
|
||||||
]);
|
]);
|
||||||
User::factory()->create([
|
|
||||||
'nama' => 'Kasir',
|
|
||||||
'role' => 'kasir',
|
|
||||||
'password' => bcrypt('123123'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
User::factory(2)->create();
|
User::factory(2)->create();
|
||||||
Sales::factory(5)->create();
|
Sales::factory(5)->create();
|
||||||
|
@ -1,42 +1,26 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, provide, computed } from "vue";
|
import { ref, provide } from "vue";
|
||||||
import NavDesktop from "./NavDesktop.vue";
|
import NavDesktop from "./NavDesktop.vue";
|
||||||
import NavMobile from "./NavMobile.vue";
|
import NavMobile from "./NavMobile.vue";
|
||||||
import logo from "../../images/logo.png";
|
import logo from "../../images/logo.png";
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
const isOpen = ref(false);
|
const isOpen = ref(false);
|
||||||
const isMobileMenuOpen = ref(false);
|
const isMobileMenuOpen = ref(false);
|
||||||
const openDropdownIndex = ref(null);
|
const openDropdownIndex = ref(null);
|
||||||
|
|
||||||
const baseItems = [
|
const items = [
|
||||||
{
|
{ label: "Manajemen Produk", subItems: [
|
||||||
label: "Manajemen Produk",
|
{ label: "Brankas", route: "/brankas" },
|
||||||
subItems: [
|
{ label: "Nampan", route: "/nampan" },
|
||||||
{ label: "Brankas", route: "/brankas" },
|
{ label: "Produk", route: "/produk" },
|
||||||
{ label: "Nampan", route: "/nampan" },
|
{ label: "Kategori", route: "/kategori" },
|
||||||
{ label: "Produk", route: "/produk" },
|
{ label: "Sales", route: "/sales" },
|
||||||
{ label: "Kategori", route: "/kategori" },
|
] },
|
||||||
{ label: "Sales", route: "/sales" },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ label: "Kasir", route: "/kasir" },
|
{ label: "Kasir", route: "/kasir" },
|
||||||
{ label: "Laporan", route: "/laporan" },
|
{ label: "Laporan", route: "/laporan" },
|
||||||
{ label: "Akun", route: "/akun" },
|
{ label: "Akun", route: "/akun" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const role = localStorage.getItem("role");
|
|
||||||
|
|
||||||
const items = computed(() => {
|
|
||||||
if (role === "owner") {
|
|
||||||
return baseItems;
|
|
||||||
}
|
|
||||||
if (role === "kasir") {
|
|
||||||
return baseItems.filter(item => !["Akun", "Laporan"].includes(item.label));
|
|
||||||
}
|
|
||||||
return baseItems;
|
|
||||||
});
|
|
||||||
|
|
||||||
const toggleDropdown = (index = null) => {
|
const toggleDropdown = (index = null) => {
|
||||||
if (index !== null) {
|
if (index !== null) {
|
||||||
openDropdownIndex.value = openDropdownIndex.value === index ? null : index;
|
openDropdownIndex.value = openDropdownIndex.value === index ? null : index;
|
||||||
@ -57,31 +41,13 @@ const closeMobileMenu = () => {
|
|||||||
openDropdownIndex.value = null;
|
openDropdownIndex.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const logout = async () => {
|
const logout = () => {
|
||||||
try {
|
console.log("Logout clicked");
|
||||||
await axios.post("/api/logout", null, {
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
localStorage.removeItem("token");
|
|
||||||
localStorage.removeItem("role");
|
|
||||||
|
|
||||||
window.location.href = "/";
|
|
||||||
} catch (error) {
|
|
||||||
if (error.response && error.response.status === 401) {
|
|
||||||
localStorage.removeItem("token");
|
|
||||||
localStorage.removeItem("role");
|
|
||||||
window.location.href = "/";
|
|
||||||
} else {
|
|
||||||
console.error("Logout failed:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closeMobileMenu();
|
closeMobileMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Provide shared data to child components
|
// Provide shared data to child components
|
||||||
provide("navigationData", {
|
provide('navigationData', {
|
||||||
logo,
|
logo,
|
||||||
items,
|
items,
|
||||||
isOpen,
|
isOpen,
|
||||||
@ -103,7 +69,10 @@ provide("navigationData", {
|
|||||||
<NavMobile />
|
<NavMobile />
|
||||||
|
|
||||||
<!-- Click Outside Handler for Desktop Dropdown -->
|
<!-- Click Outside Handler for Desktop Dropdown -->
|
||||||
<div v-if="openDropdownIndex !== null && !isMobileMenuOpen" @click="openDropdownIndex = null"
|
<div
|
||||||
class="fixed inset-0 z-10"></div>
|
v-if="openDropdownIndex !== null && !isMobileMenuOpen"
|
||||||
|
@click="openDropdownIndex = null"
|
||||||
|
class="fixed inset-0 z-10"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
export default function auth(to, from, next) {
|
|
||||||
const token = localStorage.getItem("token")
|
|
||||||
|
|
||||||
if (!token) {
|
|
||||||
next({ name: "Login" })
|
|
||||||
} else {
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
export default function guest(to, from, next) {
|
|
||||||
const token = localStorage.getItem("token")
|
|
||||||
if (token) {
|
|
||||||
next({ name: "Brankas" })
|
|
||||||
} else {
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
export default function owner(to, from, next) {
|
|
||||||
const role = localStorage.getItem("role")
|
|
||||||
if (role !== "owner") {
|
|
||||||
next({ name: "Kasir" })
|
|
||||||
} else {
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,124 +1,84 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
import Home from '../pages/Home.vue'
|
||||||
|
import Produk from '../pages/Produk.vue'
|
||||||
|
import Brankas from '../pages/Brankas.vue'
|
||||||
|
import Tray from '../pages/Tray.vue'
|
||||||
|
import Kasir from '../pages/Kasir.vue'
|
||||||
|
import InputProduk from '../pages/InputProduk.vue'
|
||||||
|
import Kategori from '../pages/Kategori.vue'
|
||||||
|
import Sales from '../pages/Sales.vue'
|
||||||
|
import EditProduk from '../pages/EditProduk.vue'
|
||||||
|
import Laporan from '../pages/Laporan.vue'
|
||||||
|
|
||||||
import Produk from "../pages/Produk.vue";
|
import Login from '../pages/Login.vue'
|
||||||
import Brankas from "../pages/Brankas.vue";
|
|
||||||
import Tray from "../pages/Tray.vue";
|
import Akun from '../pages/Akun.vue'
|
||||||
import Kasir from "../pages/Kasir.vue";
|
|
||||||
import InputProduk from "../pages/InputProduk.vue";
|
|
||||||
import Kategori from "../pages/Kategori.vue";
|
|
||||||
import Sales from "../pages/Sales.vue";
|
|
||||||
import EditProduk from "../pages/EditProduk.vue";
|
|
||||||
import Laporan from "../pages/Laporan.vue";
|
|
||||||
import Login from "../pages/Login.vue";
|
|
||||||
import Akun from "../pages/Akun.vue";
|
|
||||||
|
|
||||||
import auth from "../middlewares/auth";
|
|
||||||
import guest from "../middlewares/guest";
|
|
||||||
import owner from "../middlewares/owner";
|
|
||||||
|
|
||||||
const middlewareMap = { auth, guest, owner };
|
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: '/',
|
||||||
name: "Login",
|
name: 'Login',
|
||||||
component: Login,
|
component: Login
|
||||||
meta: { middleware: "guest" },
|
},
|
||||||
},
|
{
|
||||||
{
|
path: '/produk',
|
||||||
path: "/produk",
|
name: 'Produk',
|
||||||
name: "Produk",
|
component: Produk
|
||||||
component: Produk,
|
},
|
||||||
meta: { middleware: "auth" },
|
{
|
||||||
},
|
path: '/produk/baru',
|
||||||
{
|
name: 'ProdukBaru',
|
||||||
path: "/produk/baru",
|
component: InputProduk
|
||||||
name: "ProdukBaru",
|
},
|
||||||
component: InputProduk,
|
{
|
||||||
meta: { middleware: ["auth", "owner"] },
|
path: '/brankas',
|
||||||
},
|
name: 'Brankas',
|
||||||
{
|
component: Brankas
|
||||||
path: "/produk/:id/edit",
|
},
|
||||||
name: "EditProduk",
|
{
|
||||||
component: EditProduk,
|
path: '/nampan',
|
||||||
props: true,
|
name: 'Nampan',
|
||||||
meta: { middleware: ["auth", "owner"] },
|
component: Tray
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/brankas",
|
path: '/kasir',
|
||||||
name: "Brankas",
|
name: 'Kasir',
|
||||||
component: Brankas,
|
component: Kasir
|
||||||
meta: { middleware: "auth" },
|
},
|
||||||
},
|
{
|
||||||
{
|
path: '/kategori',
|
||||||
path: "/nampan",
|
name: 'Kategori',
|
||||||
name: "Nampan",
|
component: Kategori
|
||||||
component: Tray,
|
},
|
||||||
meta: { middleware: "auth" },
|
{
|
||||||
},
|
path: '/sales',
|
||||||
{
|
name: 'Sales',
|
||||||
path: "/sales",
|
component: Sales
|
||||||
name: "Sales",
|
},
|
||||||
component: Sales,
|
{
|
||||||
meta: { middleware: "auth" },
|
path: '/akun',
|
||||||
},
|
name: 'Akun',
|
||||||
{
|
component: Akun
|
||||||
path: "/kategori",
|
},
|
||||||
name: "Kategori",
|
{
|
||||||
component: Kategori,
|
path: '/produk/:id/edit', // :id = parameter dinamis
|
||||||
meta: { middleware: "auth" },
|
name: 'EditProduk',
|
||||||
},
|
component: EditProduk,
|
||||||
{
|
props: true // biar id bisa langsung jadi props di komponen
|
||||||
path: "/kasir",
|
},
|
||||||
name: "Kasir",
|
{
|
||||||
component: Kasir,
|
path: '/laporan',
|
||||||
meta: { middleware: "auth" },
|
name: 'EditProduk',
|
||||||
},
|
component: Laporan
|
||||||
{
|
}
|
||||||
path: "/laporan",
|
]
|
||||||
name: "Laporan",
|
|
||||||
component: Laporan,
|
|
||||||
meta: { middleware: ["auth", "owner"] },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/akun",
|
|
||||||
name: "Akun",
|
|
||||||
component: Akun,
|
|
||||||
meta: { middleware: ["auth", "owner"] },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
routes,
|
routes
|
||||||
});
|
})
|
||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
export default router
|
||||||
let middlewares = to.meta.middleware;
|
|
||||||
if (!middlewares) return next();
|
|
||||||
|
|
||||||
if (!Array.isArray(middlewares)) {
|
|
||||||
middlewares = [middlewares];
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = 0;
|
|
||||||
const run = () => {
|
|
||||||
const name = middlewares[index];
|
|
||||||
const mw = middlewareMap[name];
|
|
||||||
if (!mw) return next();
|
|
||||||
|
|
||||||
mw(to, from, (redirect) => {
|
|
||||||
if (redirect) return next(redirect);
|
|
||||||
index++;
|
|
||||||
if (index < middlewares.length) {
|
|
||||||
run();
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
run();
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
|
||||||
|
Loading…
Reference in New Issue
Block a user