Merge branch 'production' of https://git.abbauf.com/Magang-2025/Kasir into production

This commit is contained in:
timotiabbauftech 2025-09-08 11:12:26 +07:00
commit ae225ce5c7
6 changed files with 197 additions and 96 deletions

View File

@ -20,10 +20,15 @@ class DatabaseSeeder extends Seeder
public function run(): void public function run(): void
{ {
User::factory()->create([ User::factory()->create([
'nama' => 'Test', 'nama' => 'Owner',
'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();

View File

@ -1,26 +1,42 @@
<script setup> <script setup>
import { ref, provide } from "vue"; import { ref, provide, computed } 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 items = [ const baseItems = [
{ label: "Manajemen Produk", subItems: [ {
{ label: "Brankas", route: "/brankas" }, label: "Manajemen Produk",
{ label: "Nampan", route: "/nampan" }, subItems: [
{ label: "Produk", route: "/produk" }, { label: "Brankas", route: "/brankas" },
{ label: "Kategori", route: "/kategori" }, { label: "Nampan", route: "/nampan" },
{ label: "Sales", route: "/sales" }, { label: "Produk", route: "/produk" },
] }, { 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;
@ -41,13 +57,31 @@ const closeMobileMenu = () => {
openDropdownIndex.value = null; openDropdownIndex.value = null;
}; };
const logout = () => { const logout = async () => {
console.log("Logout clicked"); try {
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,
@ -64,15 +98,12 @@ provide('navigationData', {
<div class="relative"> <div class="relative">
<!-- Desktop Navigation --> <!-- Desktop Navigation -->
<NavDesktop /> <NavDesktop />
<!-- Mobile Navigation --> <!-- Mobile Navigation -->
<NavMobile /> <NavMobile />
<!-- Click Outside Handler for Desktop Dropdown --> <!-- Click Outside Handler for Desktop Dropdown -->
<div <div v-if="openDropdownIndex !== null && !isMobileMenuOpen" @click="openDropdownIndex = null"
v-if="openDropdownIndex !== null && !isMobileMenuOpen" class="fixed inset-0 z-10"></div>
@click="openDropdownIndex = null"
class="fixed inset-0 z-10"
></div>
</div> </div>
</template> </template>

View File

@ -0,0 +1,9 @@
export default function auth(to, from, next) {
const token = localStorage.getItem("token")
if (!token) {
next({ name: "Login" })
} else {
next()
}
}

View File

@ -0,0 +1,8 @@
export default function guest(to, from, next) {
const token = localStorage.getItem("token")
if (token) {
next({ name: "Brankas" })
} else {
next()
}
}

View File

@ -0,0 +1,8 @@
export default function owner(to, from, next) {
const role = localStorage.getItem("role")
if (role !== "owner") {
next({ name: "Kasir" })
} else {
next()
}
}

View File

@ -1,84 +1,124 @@
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 Login from '../pages/Login.vue' import Produk from "../pages/Produk.vue";
import Brankas from "../pages/Brankas.vue";
import Akun from '../pages/Akun.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 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', {
name: 'Produk', path: "/produk",
component: Produk name: "Produk",
}, component: Produk,
{ meta: { middleware: "auth" },
path: '/produk/baru', },
name: 'ProdukBaru', {
component: InputProduk path: "/produk/baru",
}, name: "ProdukBaru",
{ component: InputProduk,
path: '/brankas', meta: { middleware: ["auth", "owner"] },
name: 'Brankas', },
component: Brankas {
}, path: "/produk/:id/edit",
{ name: "EditProduk",
path: '/nampan', component: EditProduk,
name: 'Nampan', props: true,
component: Tray meta: { middleware: ["auth", "owner"] },
}, },
{ {
path: '/kasir', path: "/brankas",
name: 'Kasir', name: "Brankas",
component: Kasir component: Brankas,
}, meta: { middleware: "auth" },
{ },
path: '/kategori', {
name: 'Kategori', path: "/nampan",
component: Kategori name: "Nampan",
}, component: Tray,
{ meta: { middleware: "auth" },
path: '/sales', },
name: 'Sales', {
component: Sales path: "/sales",
}, name: "Sales",
{ component: Sales,
path: '/akun', meta: { middleware: "auth" },
name: 'Akun', },
component: Akun {
}, path: "/kategori",
{ name: "Kategori",
path: '/produk/:id/edit', // :id = parameter dinamis component: Kategori,
name: 'EditProduk', meta: { middleware: "auth" },
component: EditProduk, },
props: true // biar id bisa langsung jadi props di komponen {
}, path: "/kasir",
{ name: "Kasir",
path: '/laporan', component: Kasir,
name: 'EditProduk', meta: { middleware: "auth" },
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,
}) });
export default router router.beforeEach((to, from, next) => {
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;