update case index page segment index and show page

This commit is contained in:
Simon Pocrnjič
2025-12-14 20:57:39 +01:00
parent a6ec92ec6b
commit 80948d2944
14 changed files with 1141 additions and 626 deletions
+48 -90
View File
@@ -1,5 +1,5 @@
<script setup>
import { onMounted, onUnmounted, ref, watch, computed } from "vue";
import { onMounted, onUnmounted, ref, watch, computed, h } from "vue";
import { Head, Link, router, usePage } from "@inertiajs/vue3";
import ApplicationMark from "@/Components/ApplicationMark.vue";
import Banner from "@/Components/Banner.vue";
@@ -23,6 +23,22 @@ import {
faMap,
faGear,
} from "@fortawesome/free-solid-svg-icons";
import { MenuIcon } from "lucide-vue-next";
import { SearchIcon } from "lucide-vue-next";
import { ChevronDownIcon } from "lucide-vue-next";
import { LayoutDashboardIcon } from "lucide-vue-next";
import { FileChartColumn } from "lucide-vue-next";
import { UsersIcon } from "lucide-vue-next";
import { FoldersIcon } from "lucide-vue-next";
import { LayoutIcon } from "lucide-vue-next";
import { ImportIcon } from "lucide-vue-next";
import { FilePlusIcon } from "lucide-vue-next";
import { ListIndentIncreaseIcon } from "lucide-vue-next";
import { MapIcon } from "lucide-vue-next";
import { SettingsIcon } from "lucide-vue-next";
import { ShieldUserIcon } from "lucide-vue-next";
import { SmartphoneIcon } from "lucide-vue-next";
import { TabletSmartphoneIcon } from "lucide-vue-next";
const props = defineProps({
title: String,
@@ -115,12 +131,14 @@ const rawMenuGroups = [
items: [
{
key: "dashboard",
icon: LayoutDashboardIcon,
title: "Nadzorna plošča",
routeName: "dashboard",
active: ["dashboard"],
},
{
key: "reports",
icon: FileChartColumn,
title: "Poročila",
routeName: "reports.index",
active: ["reports.index", "reports.show"],
@@ -133,18 +151,21 @@ const rawMenuGroups = [
items: [
{
key: "clients",
icon: UsersIcon,
title: "Naročniki",
routeName: "client",
active: ["client", "client.*"],
},
{
key: "cases",
icon: FoldersIcon,
title: "Primeri",
routeName: "clientCase",
active: ["clientCase", "clientCase.*"],
},
{
key: "segments",
icon: LayoutIcon,
title: "Segmenti",
routeName: "segments.index",
active: ["segments.index"],
@@ -157,18 +178,21 @@ const rawMenuGroups = [
items: [
{
key: "imports",
icon: ImportIcon,
title: "Uvozi",
routeName: "imports.index",
active: ["imports.index", "imports.*"],
},
{
key: "import-templates",
icon: ListIndentIncreaseIcon,
title: "Uvozne predloge",
routeName: "importTemplates.index",
active: ["importTemplates.index"],
},
{
key: "import-templates-new",
icon: FilePlusIcon,
title: "Nova uvozna predloga",
routeName: "importTemplates.create",
active: ["importTemplates.create"],
@@ -181,6 +205,7 @@ const rawMenuGroups = [
items: [
{
key: "fieldjobs",
icon: MapIcon,
title: "Terenske naloge",
routeName: "fieldjobs.index",
active: ["fieldjobs.index"],
@@ -195,6 +220,7 @@ const rawMenuGroups = [
items: [
{
key: "settings",
icon: SettingsIcon,
title: "Nastavitve",
routeName: "settings",
active: ["settings", "settings.*"],
@@ -204,6 +230,7 @@ const rawMenuGroups = [
// We'll filter it out below if not authorized.
{
key: "admin-panel",
icon: ShieldUserIcon,
title: "Administrator",
routeName: "admin.index",
active: ["admin.index", "admin.users.index", "admin.permissions.create"],
@@ -247,21 +274,6 @@ const menuGroups = computed(() => {
);
});
// Icon map for menu keys -> FontAwesome icon definitions
const menuIconMap = {
dashboard: faGaugeHigh,
segments: faLayerGroup,
clients: faUserGroup,
cases: faFolderOpen,
imports: faFileImport,
"import-templates": faTableList,
"import-templates-new": faFileCirclePlus,
fieldjobs: faMap,
settings: faGear,
"admin-panel": faUserGroup,
reports: faTableList,
};
function isActive(patterns) {
try {
return patterns?.some((p) => route().current(p));
@@ -289,7 +301,7 @@ function isActive(patterns) {
<aside
:class="[
sidebarCollapsed ? 'w-16' : 'w-64',
'bg-white border-r border-gray-200 transition-all duration-300 ease-in-out z-50',
'bg-sidebar text-sidebar-foreground border-r border-sidebar-border transition-all duration-300 ease-in-out z-50',
// Off-canvas behavior on mobile; sticky fixed-like sidebar on desktop
isMobile
? 'fixed inset-y-0 left-0 transform shadow-strong ' +
@@ -297,7 +309,9 @@ function isActive(patterns) {
: 'sticky top-0 h-screen overflow-y-auto',
]"
>
<div class="h-16 px-4 flex items-center justify-between border-b border-gray-200 bg-white">
<div
class="h-16 px-4 flex items-center justify-between border-b border-sidebar-border bg-sidebar"
>
<Link
:href="route('dashboard')"
class="flex items-center gap-2 hover:opacity-80 transition-opacity"
@@ -305,7 +319,7 @@ function isActive(patterns) {
<ApplicationMark />
<span
v-if="!sidebarCollapsed"
class="text-sm font-semibold text-gray-900 transition-opacity"
class="text-sm font-semibold text-sidebar-foreground transition-opacity"
>
Teren
</span>
@@ -316,7 +330,7 @@ function isActive(patterns) {
<li v-for="group in menuGroups" :key="group.label">
<div
v-if="!sidebarCollapsed"
class="px-4 py-1.5 text-[11px] font-semibold uppercase tracking-wider text-gray-400"
class="px-4 py-1.5 text-[11px] font-semibold uppercase tracking-wider text-sidebar-foreground/60"
>
{{ group.label }}
</div>
@@ -327,19 +341,15 @@ function isActive(patterns) {
:class="[
'flex items-center gap-3 px-3 py-2.5 text-sm rounded-lg transition-all duration-150',
isActive(item.active)
? 'bg-primary-50 text-primary-700 font-medium shadow-sm'
: 'text-gray-600 hover:bg-gray-50 hover:text-gray-900',
? 'bg-sidebar-primary/15 text-sidebar-primary font-medium shadow-sm'
: 'text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
]"
:title="item.title"
>
<!-- Unified FontAwesome icon rendering -->
<FontAwesomeIcon
v-if="menuIconMap[item.key]"
:icon="menuIconMap[item.key]"
:class="[
'w-5 h-5 flex-shrink-0 transition-colors',
isActive(item.active) ? 'text-primary-600' : 'text-gray-500',
]"
<component
v-if="item.icon"
:is="item.icon"
class="w-5 h-5 shrink-0 transition-colors"
/>
<!-- Title -->
<span
@@ -361,7 +371,7 @@ function isActive(patterns) {
<div class="flex-1 flex flex-col min-w-0">
<!-- Top bar -->
<div
class="h-16 bg-white border-b border-gray-200 px-4 flex items-center justify-between sticky top-0 z-30 backdrop-blur-sm bg-white/95 shadow-sm"
class="h-16 border-b border-gray-200 px-4 flex items-center justify-between sticky top-0 z-30 backdrop-blur-sm bg-white/95 shadow-sm"
>
<div class="flex items-center gap-3">
<!-- Sidebar toggle -->
@@ -373,42 +383,11 @@ function isActive(patterns) {
aria-label="Toggle sidebar"
>
<!-- Hamburger (Bars) icon -->
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-5 h-5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
/>
</svg>
<MenuIcon />
</Button>
<!-- Search trigger -->
<Button
variant="outline"
size="default"
@click="openSearch"
class="gap-2"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M21 21l-4.35-4.35m0 0A7.5 7.5 0 1010.5 18.5a7.5 7.5 0 006.15-1.85z"
/>
</svg>
<Button variant="outline" size="default" @click="openSearch" class="gap-2">
<SearchIcon />
<span class="hidden sm:inline text-sm font-medium">Globalni iskalnik</span>
<kbd
class="hidden sm:inline ml-2 text-[10px] px-1.5 py-0.5 rounded border border-gray-300 bg-gray-100 text-gray-600 font-medium"
@@ -428,7 +407,7 @@ function isActive(patterns) {
title="Phone"
>
<Link :href="route('phone.index')">
<FontAwesomeIcon :icon="faMobileScreenButton" class="h-5 w-5" />
<TabletSmartphoneIcon />
</Link>
</Button>
<div class="ms-3 relative">
@@ -446,27 +425,9 @@ function isActive(patterns) {
</button>
<span v-else class="inline-flex">
<Button
variant="outline"
size="default"
type="button"
class="gap-2"
>
<Button variant="outline" size="default" type="button" class="gap-2">
{{ $page.props.auth.user.name }}
<svg
class="h-4 w-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M19.5 8.25l-7.5 7.5-7.5-7.5"
/>
</svg>
<ChevronDownIcon />
</Button>
</span>
</template>
@@ -495,10 +456,7 @@ function isActive(patterns) {
</div>
<!-- Page Heading -->
<header
v-if="$slots.header"
class="bg-white border-b border-gray-200 shadow-sm"
>
<header v-if="$slots.header" class="bg-white border-b border-gray-200 shadow-sm">
<div class="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8 space-y-2">
<Breadcrumbs
v-if="$page.props.breadcrumbs && $page.props.breadcrumbs.length"