From db99a57030a0c1f3e14c8708f93528fa9ac382fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Pocrnji=C4=8D?= Date: Tue, 30 Sep 2025 22:00:03 +0200 Subject: [PATCH] changes to UI mostly --- app/Http/Controllers/ClientCaseContoller.php | 122 ++++- app/Http/Controllers/ClientController.php | 75 ++- app/Http/Controllers/FieldJobController.php | 9 +- app/Http/Controllers/SegmentController.php | 87 +++- resources/js/Components/Pagination.vue | 258 +++++++--- resources/js/Layouts/AppLayout.vue | 8 + resources/js/Pages/Cases/Index.vue | 162 ++++-- .../js/Pages/Cases/Partials/ActivityTable.vue | 194 +++++-- .../Pages/Cases/Partials/ContractDrawer.vue | 15 +- resources/js/Pages/Cases/Show.vue | 235 ++++++--- resources/js/Pages/Client/Index.vue | 478 ++++++++++-------- resources/js/Pages/Client/Show.vue | 221 +++++--- resources/js/Pages/FieldJob/Index.vue | 334 +++++++++--- resources/js/Pages/Phone/Case/Index.vue | 443 ++++++++++------ resources/js/Pages/Phone/Index.vue | 37 +- resources/js/Pages/Segments/Index.vue | 107 ++++ resources/js/Pages/Segments/Show.vue | 156 ++++++ routes/web.php | 5 + 18 files changed, 2169 insertions(+), 777 deletions(-) create mode 100644 resources/js/Pages/Segments/Index.vue create mode 100644 resources/js/Pages/Segments/Show.vue diff --git a/app/Http/Controllers/ClientCaseContoller.php b/app/Http/Controllers/ClientCaseContoller.php index 14261f9..705fb55 100644 --- a/app/Http/Controllers/ClientCaseContoller.php +++ b/app/Http/Controllers/ClientCaseContoller.php @@ -20,15 +20,43 @@ class ClientCaseContoller extends Controller */ public function index(ClientCase $clientCase, Request $request) { + $query = $clientCase::query() + ->with(['person', 'client.person']) + ->where('active', 1) + ->when($request->input('search'), function ($que, $search) { + $que->whereHas('person', function ($q) use ($search) { + $q->where('full_name', 'ilike', '%'.$search.'%'); + }); + }) + ->addSelect([ + // Count of active contracts (a contract is considered active if it has an active pivot in contract_segment) + 'active_contracts_count' => \DB::query() + ->from('contracts') + ->selectRaw('COUNT(*)') + ->whereColumn('contracts.client_case_id', 'client_cases.id') + ->whereNull('contracts.deleted_at') + ->whereExists(function ($q) { + $q->from('contract_segment') + ->whereColumn('contract_segment.contract_id', 'contracts.id') + ->where('contract_segment.active', true); + }), + // Sum of balances for accounts of active contracts + 'active_contracts_balance_sum' => \DB::query() + ->from('contracts') + ->join('accounts', 'accounts.contract_id', '=', 'contracts.id') + ->selectRaw('COALESCE(SUM(accounts.balance_amount), 0)') + ->whereColumn('contracts.client_case_id', 'client_cases.id') + ->whereNull('contracts.deleted_at') + ->whereExists(function ($q) { + $q->from('contract_segment') + ->whereColumn('contract_segment.contract_id', 'contracts.id') + ->where('contract_segment.active', true); + }), + ]) + ->orderByDesc('created_at'); + return Inertia::render('Cases/Index', [ - 'client_cases' => $clientCase::with(['person']) - ->when($request->input('search'), fn ($que, $search) => $que->whereHas( - 'person', - fn ($q) => $q->where('full_name', 'ilike', '%'.$search.'%') - ) - ) - ->where('active', 1) - ->orderByDesc('created_at') + 'client_cases' => $query ->paginate(15, ['*'], 'client-cases-page') ->withQueryString(), 'filters' => $request->only(['search']), @@ -122,7 +150,9 @@ public function storeContract(ClientCase $clientCase, StoreContractRequest $requ }); - return to_route('clientCase.show', $clientCase); + // Preserve segment filter if present + $segment = request('segment'); + return to_route('clientCase.show', ['client_case' => $clientCase, 'segment' => $segment]); } public function updateContract(ClientCase $clientCase, string $uuid, UpdateContractRequest $request) @@ -163,7 +193,9 @@ public function updateContract(ClientCase $clientCase, string $uuid, UpdateContr }); - return to_route('clientCase.show', $clientCase); + // Preserve segment filter if present + $segment = request('segment'); + return to_route('clientCase.show', ['client_case' => $clientCase, 'segment' => $segment]); } public function storeActivity(ClientCase $clientCase, Request $request) @@ -219,6 +251,20 @@ public function storeActivity(ClientCase $clientCase, Request $request) } + public function deleteActivity(ClientCase $clientCase, \App\Models\Activity $activity, Request $request) + { + // Ensure activity belongs to this case + if ($activity->client_case_id !== $clientCase->id) { + abort(404); + } + + \DB::transaction(function () use ($activity) { + $activity->delete(); + }); + + return back()->with('success', 'Activity deleted.'); + } + public function deleteContract(ClientCase $clientCase, string $uuid, Request $request) { $contract = Contract::where('uuid', $uuid)->firstOrFail(); @@ -227,7 +273,9 @@ public function deleteContract(ClientCase $clientCase, string $uuid, Request $re $contract->delete(); }); - return to_route('clientCase.show', $clientCase); + // Preserve segment filter if present + $segment = request('segment'); + return to_route('clientCase.show', ['client_case' => $clientCase, 'segment' => $segment]); } public function updateContractSegment(ClientCase $clientCase, string $uuid, Request $request) @@ -923,11 +971,25 @@ public function show(ClientCase $clientCase) 'phone_types' => \App\Models\Person\PhoneType::all(), ]; + // Optional segment filter from query string + $segmentId = request()->integer('segment'); + // Prepare contracts and a reference map - $contracts = $case->contracts() + $contractsQuery = $case->contracts() ->with(['type', 'account', 'objects', 'segments:id,name']) - ->orderByDesc('created_at') - ->get(); + ->orderByDesc('created_at'); + + if (! empty($segmentId)) { + // Filter to contracts that are in the provided segment and active on pivot + $contractsQuery->whereExists(function ($q) use ($segmentId) { + $q->from('contract_segment') + ->whereColumn('contract_segment.contract_id', 'contracts.id') + ->where('contract_segment.segment_id', $segmentId) + ->where('contract_segment.active', true); + }); + } + + $contracts = $contractsQuery->get(); $contractRefMap = []; foreach ($contracts as $c) { $contractRefMap[$c->id] = $c->reference; @@ -937,11 +999,11 @@ public function show(ClientCase $clientCase) $contractIds = $contracts->pluck('id'); $contractDocs = Document::query() ->where('documentable_type', Contract::class) - ->whereIn('documentable_id', $contractIds) + ->when($contractIds->isNotEmpty(), fn ($q) => $q->whereIn('documentable_id', $contractIds)) ->orderByDesc('created_at') ->get() ->map(function ($d) use ($contractRefMap) { - $arr = $d->toArray(); + $arr = method_exists($d, 'toArray') ? $d->toArray() : (array) $d; $arr['contract_reference'] = $contractRefMap[$d->documentable_id] ?? null; $arr['documentable_type'] = Contract::class; $arr['contract_uuid'] = optional(Contract::withTrashed()->find($d->documentable_id))->uuid; @@ -950,7 +1012,7 @@ public function show(ClientCase $clientCase) }); $caseDocs = $case->documents()->orderByDesc('created_at')->get()->map(function ($d) use ($case) { - $arr = $d->toArray(); + $arr = method_exists($d, 'toArray') ? $d->toArray() : (array) $d; $arr['documentable_type'] = ClientCase::class; $arr['client_case_uuid'] = $case->uuid; @@ -961,15 +1023,32 @@ public function show(ClientCase $clientCase) ->sortByDesc('created_at') ->values(); + // Resolve current segment for display when filtered + $currentSegment = null; + if (! empty($segmentId)) { + $currentSegment = \App\Models\Segment::query()->select('id', 'name')->find($segmentId); + } + return Inertia::render('Cases/Show', [ 'client' => $case->client()->with('person', fn ($q) => $q->with(['addresses', 'phones', 'bankAccounts']))->firstOrFail(), 'client_case' => $case, 'contracts' => $contracts, 'activities' => tap( - $case->activities() - ->with(['action', 'decision', 'contract:id,uuid,reference', 'user:id,name']) - ->orderByDesc('created_at') - ->paginate(20, ['*'], 'activities'), + (function () use ($case, $segmentId, $contractIds) { + $q = $case->activities() + ->with(['action', 'decision', 'contract:id,uuid,reference', 'user:id,name']) + ->orderByDesc('created_at'); + if (! empty($segmentId)) { + // Only activities for filtered contracts or unlinked (contract_id null) + $q->where(function ($qq) use ($contractIds) { + $qq->whereNull('contract_id'); + if ($contractIds->isNotEmpty()) { + $qq->orWhereIn('contract_id', $contractIds); + } + }); + } + return $q->paginate(20, ['*'], 'activities')->withQueryString(); + })(), function ($p) { $p->getCollection()->transform(function ($a) { $a->setAttribute('user_name', optional($a->user)->name); @@ -984,6 +1063,7 @@ function ($p) { 'types' => $types, 'segments' => $case->segments()->wherePivot('active', true)->get(['segments.id', 'segments.name']), 'all_segments' => \App\Models\Segment::query()->where('active', true)->get(['id', 'name']), + 'current_segment' => $currentSegment, ]); } diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index 79c2cde..45ce300 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -11,16 +11,48 @@ class ClientController extends Controller { public function index(Client $client, Request $request) { + $query = $client::query() + ->with('person') + ->when($request->input('search'), function ($que, $search) { + $que->whereHas('person', function ($q) use ($search) { + $q->where('full_name', 'ilike', '%'.$search.'%'); + }); + }) + ->where('active', 1) + ->addSelect([ + // Number of client cases for this client that have at least one active contract + 'cases_with_active_contracts_count' => DB::query() + ->from('client_cases') + ->join('contracts', 'contracts.client_case_id', '=', 'client_cases.id') + ->selectRaw('COUNT(DISTINCT client_cases.id)') + ->whereColumn('client_cases.client_id', 'clients.id') + ->whereNull('contracts.deleted_at') + ->whereExists(function ($q) { + $q->from('contract_segment') + ->whereColumn('contract_segment.contract_id', 'contracts.id') + ->where('contract_segment.active', true); + }), + // Sum of account balances for active contracts that belong to this client's cases + 'active_contracts_balance_sum' => DB::query() + ->from('contracts') + ->join('accounts', 'accounts.contract_id', '=', 'contracts.id') + ->selectRaw('COALESCE(SUM(accounts.balance_amount), 0)') + ->whereExists(function ($q) { + $q->from('client_cases') + ->whereColumn('client_cases.id', 'contracts.client_case_id') + ->whereColumn('client_cases.client_id', 'clients.id'); + }) + ->whereNull('contracts.deleted_at') + ->whereExists(function ($q) { + $q->from('contract_segment') + ->whereColumn('contract_segment.contract_id', 'contracts.id') + ->where('contract_segment.active', true); + }), + ]) + ->orderByDesc('created_at'); + return Inertia::render('Client/Index', [ - 'clients' => $client::query() - ->with('person') - ->when($request->input('search'), fn ($que, $search) => $que->whereHas( - 'person', - fn ($q) => $q->where('full_name', 'ilike', '%'.$search.'%') - ) - ) - ->where('active', 1) - ->orderByDesc('created_at') + 'clients' => $query ->paginate(15) ->withQueryString(), 'filters' => $request->only(['search']), @@ -42,12 +74,35 @@ public function show(Client $client, Request $request) return Inertia::render('Client/Show', [ 'client' => $data, 'client_cases' => $data->clientCases() - ->with('person') + ->with(['person', 'client.person']) ->when($request->input('search'), fn ($que, $search) => $que->whereHas( 'person', fn ($q) => $q->where('full_name', 'ilike', '%'.$search.'%') ) ) + ->addSelect([ + 'active_contracts_count' => \DB::query() + ->from('contracts') + ->selectRaw('COUNT(*)') + ->whereColumn('contracts.client_case_id', 'client_cases.id') + ->whereNull('contracts.deleted_at') + ->whereExists(function ($q) { + $q->from('contract_segment') + ->whereColumn('contract_segment.contract_id', 'contracts.id') + ->where('contract_segment.active', true); + }), + 'active_contracts_balance_sum' => \DB::query() + ->from('contracts') + ->join('accounts', 'accounts.contract_id', '=', 'contracts.id') + ->selectRaw('COALESCE(SUM(accounts.balance_amount), 0)') + ->whereColumn('contracts.client_case_id', 'client_cases.id') + ->whereNull('contracts.deleted_at') + ->whereExists(function ($q) { + $q->from('contract_segment') + ->whereColumn('contract_segment.contract_id', 'contracts.id') + ->where('contract_segment.active', true); + }), + ]) ->where('active', 1) ->orderByDesc('created_at') ->paginate(15) diff --git a/app/Http/Controllers/FieldJobController.php b/app/Http/Controllers/FieldJobController.php index 76bf5e3..0fe98fa 100644 --- a/app/Http/Controllers/FieldJobController.php +++ b/app/Http/Controllers/FieldJobController.php @@ -24,7 +24,7 @@ public function index(Request $request) ])->filter()->unique()->values(); $contracts = Contract::query() - ->with(['clientCase.person', 'type', 'account']) + ->with(['clientCase.person', 'clientCase.client.person', 'type', 'account']) ->when($segmentIds->isNotEmpty(), function ($q) use ($segmentIds) { $q->whereHas('segments', function ($sq) use ($segmentIds) { // Relation already filters on active pivots @@ -38,6 +38,13 @@ public function index(Request $request) ->limit(50) ->get(); + // Mirror client onto the contract for simpler frontend access: c.client.person.full_name + $contracts->each(function (Contract $contract): void { + if ($contract->relationLoaded('clientCase') && $contract->clientCase) { + $contract->setRelation('client', $contract->clientCase->client); + } + }); + // Build active assignment map keyed by contract uuid for quicker UI checks $assignments = collect(); if ($contracts->isNotEmpty()) { diff --git a/app/Http/Controllers/SegmentController.php b/app/Http/Controllers/SegmentController.php index dfef658..0cf69c6 100644 --- a/app/Http/Controllers/SegmentController.php +++ b/app/Http/Controllers/SegmentController.php @@ -2,14 +2,98 @@ namespace App\Http\Controllers; -use App\Models\Segment; use App\Http\Requests\StoreSegmentRequest; use App\Http\Requests\UpdateSegmentRequest; +use App\Models\Segment; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; use Inertia\Inertia; class SegmentController extends Controller { + public function index() + { + // Fetch active segments with number of active contracts and total balance sum of those contracts + // A contract is considered in a segment when the pivot is active=true. + $segments = Segment::query() + ->where('active', true) + ->withCount(['contracts as contracts_count' => function ($q) { + // On some drivers, wherePivot can compile oddly inside withCount; target the pivot table directly + $q->where('contract_segment.active', '=', 1); + }]) + ->get(['id', 'name', 'description']); + + // Compute total balance per segment for active contracts + $balances = DB::table('segments') + ->join('contract_segment', 'contract_segment.segment_id', '=', 'segments.id') + ->join('contracts', 'contracts.id', '=', 'contract_segment.contract_id') + ->leftJoin('accounts', 'accounts.contract_id', '=', 'contracts.id') + ->where('segments.active', '=', 1) + ->where('contract_segment.active', '=', 1) + ->groupBy('segments.id') + ->pluck(DB::raw('COALESCE(SUM(accounts.balance_amount),0) as total_balance'), 'segments.id'); + + $segments = $segments->map(function ($seg) use ($balances) { + $seg->total_balance = (string) ($balances[$seg->id] ?? 0); + + return $seg; + }); + + return Inertia::render('Segments/Index', [ + 'segments' => $segments, + ]); + } + + public function show(\App\Models\Segment $segment) + { + // Retrieve contracts that are active in this segment, eager-loading required relations + $search = request('search'); + $contractsQuery = \App\Models\Contract::query() + ->whereHas('segments', function ($q) use ($segment) { + $q->where('segments.id', $segment->id) + ->where('contract_segment.active', '=', 1); + }) + ->with([ + 'clientCase.person', + 'clientCase.client.person', + 'type', + 'account', + ]) + ->latest('id'); + + if (!empty($search)) { + $contractsQuery->where(function ($qq) use ($search) { + $qq->where('contracts.reference', 'ilike', '%'.$search.'%') + ->orWhereHas('clientCase.person', function ($p) use ($search) { + $p->where('full_name', 'ilike', '%'.$search.'%'); + }) + ->orWhereHas('clientCase.client.person', function ($p) use ($search) { + $p->where('full_name', 'ilike', '%'.$search.'%'); + }); + }); + } + + $contracts = $contractsQuery + ->paginate(15) + ->withQueryString(); + + // Mirror client onto the contract to simplify frontend access (c.client.person.full_name) + $items = collect($contracts->items()); + $items->each(function ($contract) { + if ($contract->relationLoaded('clientCase') && $contract->clientCase) { + $contract->setRelation('client', $contract->clientCase->client); + } + }); + if (method_exists($contracts, 'setCollection')) { + $contracts->setCollection($items); + } + + return Inertia::render('Segments/Show', [ + 'segment' => $segment->only(['id','name','description']), + 'contracts' => $contracts, + ]); + } + public function settings(Request $request) { return Inertia::render('Settings/Segments/Index', [ @@ -41,4 +125,3 @@ public function update(UpdateSegmentRequest $request, Segment $segment) return to_route('settings.segments')->with('success', 'Segment updated'); } } - diff --git a/resources/js/Components/Pagination.vue b/resources/js/Components/Pagination.vue index ed60bd6..874cd93 100644 --- a/resources/js/Components/Pagination.vue +++ b/resources/js/Components/Pagination.vue @@ -1,76 +1,200 @@ \ No newline at end of file + + + diff --git a/resources/js/Layouts/AppLayout.vue b/resources/js/Layouts/AppLayout.vue index 23ccbc4..76652b7 100644 --- a/resources/js/Layouts/AppLayout.vue +++ b/resources/js/Layouts/AppLayout.vue @@ -145,6 +145,14 @@ watch( Nadzorna plošča +
  • + + + + + Segmenti + +
  • diff --git a/resources/js/Pages/Cases/Index.vue b/resources/js/Pages/Cases/Index.vue index b250d05..2cbbff4 100644 --- a/resources/js/Pages/Cases/Index.vue +++ b/resources/js/Pages/Cases/Index.vue @@ -1,59 +1,121 @@

    - Contracts -

    - -
    -
    -
    -
    -
    - -
    - - -
    -
    -
    -

    {{ clientCase.person.full_name }}

    -

    {{ clientCase.person.nu }}

    -
    -
    - -
    -
    -
    -
    - -
    + + +
    +
    +
    +
    +
    + + + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Št.PrimerStrankaDavčnaAktivne pogodbeSkupaj stanje
    {{ c.person?.nu || "-" }} + + {{ c.person?.full_name || "-" }} + + {{ c.client?.person?.full_name || "-" }}{{ c.person?.tax_number || "-" }} + {{ c.active_contracts_count ?? 0 }} + + {{ fmtCurrency(c.active_contracts_balance_sum) }} +
    Ni zadetkov.
    +
    +
    +
    - - \ No newline at end of file +
    +
    +
    + diff --git a/resources/js/Pages/Cases/Partials/ActivityTable.vue b/resources/js/Pages/Cases/Partials/ActivityTable.vue index f31f7b9..147ce97 100644 --- a/resources/js/Pages/Cases/Partials/ActivityTable.vue +++ b/resources/js/Pages/Cases/Partials/ActivityTable.vue @@ -1,53 +1,163 @@ + \ No newline at end of file +
    + + + Pogodba + Datum + Akcija + Odločitev + Opomba + Datum zapadlosti + Znesek obljube + Dodal + + + + + + {{ + row.contract?.reference || "" + }} + {{ fmtDate(row.created_at) }} + {{ row.action?.name || "" }} + {{ row.decision?.name || "" }} + {{ row.note || "" }} + {{ fmtDate(row.due_date) }} + {{ + fmtCurrency(row.amount) + }} + {{ + row.user?.name || row.user_name || "" + }} + + + + + + + + + + Ni aktivnosti. + + + +
    + + + + + + + + diff --git a/resources/js/Pages/Cases/Partials/ContractDrawer.vue b/resources/js/Pages/Cases/Partials/ContractDrawer.vue index be0721d..a724791 100644 --- a/resources/js/Pages/Cases/Partials/ContractDrawer.vue +++ b/resources/js/Pages/Cases/Partials/ContractDrawer.vue @@ -94,10 +94,21 @@ const storeOrUpdate = () => { }, preserveScroll: true, } + const params = {} + try { + const url = new URL(window.location.href) + const seg = url.searchParams.get('segment') + if (seg) params.segment = seg + } catch (e) {} if (isEdit) { - formContract.put(route('clientCase.contract.update', { client_case: props.client_case.uuid, uuid: formContract.uuid }), options) + formContract.put(route('clientCase.contract.update', { client_case: props.client_case.uuid, uuid: formContract.uuid, ...params }), options) } else { - formContract.post(route('clientCase.contract.store', props.client_case), options) + // route helper merges params for GET; for POST we can append query manually if needed + let postUrl = route('clientCase.contract.store', props.client_case) + if (params.segment) { + postUrl += (postUrl.includes('?') ? '&' : '?') + 'segment=' + encodeURIComponent(params.segment) + } + formContract.post(postUrl, options) } } diff --git a/resources/js/Pages/Cases/Show.vue b/resources/js/Pages/Cases/Show.vue index 1cad929..be88263 100644 --- a/resources/js/Pages/Cases/Show.vue +++ b/resources/js/Pages/Cases/Show.vue @@ -12,11 +12,11 @@ import DocumentsTable from "@/Components/DocumentsTable.vue"; import DocumentUploadDialog from "@/Components/DocumentUploadDialog.vue"; import DocumentViewerDialog from "@/Components/DocumentViewerDialog.vue"; import { classifyDocument } from "@/Services/documents"; -import { router, useForm } from '@inertiajs/vue3'; +import { router, useForm } from "@inertiajs/vue3"; import { AngleDownIcon, AngleUpIcon } from "@/Utilities/Icons"; import Pagination from "@/Components/Pagination.vue"; import ConfirmDialog from "@/Components/ConfirmDialog.vue"; -import DialogModal from '@/Components/DialogModal.vue'; +import DialogModal from "@/Components/DialogModal.vue"; const props = defineProps({ client: Object, @@ -30,33 +30,55 @@ const props = defineProps({ documents: Array, segments: { type: Array, default: () => [] }, all_segments: { type: Array, default: () => [] }, + current_segment: { type: Object, default: null }, }); const showUpload = ref(false); -const openUpload = () => { showUpload.value = true; }; -const closeUpload = () => { showUpload.value = false; }; +const openUpload = () => { + showUpload.value = true; +}; +const closeUpload = () => { + showUpload.value = false; +}; const onUploaded = () => { // Refresh page data to include the new document - router.reload({ only: ['documents'] }); + router.reload({ only: ["documents"] }); }; -const viewer = ref({ open: false, src: '', title: '' }); +const viewer = ref({ open: false, src: "", title: "" }); const openViewer = (doc) => { - const kind = classifyDocument(doc) - const isContractDoc = (doc?.documentable_type || '').toLowerCase().includes('contract') - if (kind === 'preview') { - const url = isContractDoc && doc.contract_uuid - ? route('contract.document.view', { contract: doc.contract_uuid, document: doc.uuid }) - : route('clientCase.document.view', { client_case: props.client_case.uuid, document: doc.uuid }) - viewer.value = { open: true, src: url, title: doc.original_name || doc.name } + const kind = classifyDocument(doc); + const isContractDoc = (doc?.documentable_type || "").toLowerCase().includes("contract"); + if (kind === "preview") { + const url = + isContractDoc && doc.contract_uuid + ? route("contract.document.view", { + contract: doc.contract_uuid, + document: doc.uuid, + }) + : route("clientCase.document.view", { + client_case: props.client_case.uuid, + document: doc.uuid, + }); + viewer.value = { open: true, src: url, title: doc.original_name || doc.name }; } else { - const url = isContractDoc && doc.contract_uuid - ? route('contract.document.download', { contract: doc.contract_uuid, document: doc.uuid }) - : route('clientCase.document.download', { client_case: props.client_case.uuid, document: doc.uuid }) - window.location.href = url + const url = + isContractDoc && doc.contract_uuid + ? route("contract.document.download", { + contract: doc.contract_uuid, + document: doc.uuid, + }) + : route("clientCase.document.download", { + client_case: props.client_case.uuid, + document: doc.uuid, + }); + window.location.href = url; } -} -const closeViewer = () => { viewer.value.open = false; viewer.value.src = ''; }; +}; +const closeViewer = () => { + viewer.value.open = false; + viewer.value.src = ""; +}; const clientDetails = ref(false); @@ -82,17 +104,36 @@ const openDrawerAddActivity = (c = null) => { }; // delete confirmation -const confirmDelete = ref({ show: false, contract: null }) -const requestDeleteContract = (c) => { confirmDelete.value = { show: true, contract: c } } -const closeConfirmDelete = () => { confirmDelete.value.show = false; confirmDelete.value.contract = null } +const confirmDelete = ref({ show: false, contract: null }); +const requestDeleteContract = (c) => { + confirmDelete.value = { show: true, contract: c }; +}; +const closeConfirmDelete = () => { + confirmDelete.value.show = false; + confirmDelete.value.contract = null; +}; const doDeleteContract = () => { - const c = confirmDelete.value.contract - if (!c) return closeConfirmDelete() - router.delete(route('clientCase.contract.delete', { client_case: props.client_case.uuid, uuid: c.uuid }), { - preserveScroll: true, - onFinish: () => closeConfirmDelete(), - }) -} + const c = confirmDelete.value.contract; + if (!c) return closeConfirmDelete(); + // Keep segment filter in redirect + const params = {}; + try { + const url = new URL(window.location.href); + const seg = url.searchParams.get("segment"); + if (seg) params.segment = seg; + } catch (e) {} + router.delete( + route("clientCase.contract.delete", { + client_case: props.client_case.uuid, + uuid: c.uuid, + ...params, + }), + { + preserveScroll: true, + onFinish: () => closeConfirmDelete(), + } + ); +}; //Close drawer (all) const closeDrawer = () => { @@ -109,35 +150,52 @@ const hideClietnDetails = () => { }; // Attach segment to case -const showAttachSegment = ref(false) -const openAttachSegment = () => { showAttachSegment.value = true } -const closeAttachSegment = () => { showAttachSegment.value = false } -const attachForm = useForm({ segment_id: null }) +const showAttachSegment = ref(false); +const openAttachSegment = () => { + showAttachSegment.value = true; +}; +const closeAttachSegment = () => { + showAttachSegment.value = false; +}; +const attachForm = useForm({ segment_id: null }); const availableSegments = computed(() => { - const current = new Set((props.segments || []).map(s => s.id)) - return (props.all_segments || []).filter(s => !current.has(s.id)) -}) + const current = new Set((props.segments || []).map((s) => s.id)); + return (props.all_segments || []).filter((s) => !current.has(s.id)); +}); const submitAttachSegment = () => { - if (!attachForm.segment_id) { return } - attachForm.post(route('clientCase.segments.attach', props.client_case), { + if (!attachForm.segment_id) { + return; + } + attachForm.post(route("clientCase.segments.attach", props.client_case), { preserveScroll: true, - only: ['segments'], + only: ["segments"], onSuccess: () => { - closeAttachSegment() - attachForm.reset('segment_id') - } - }) -} + closeAttachSegment(); + attachForm.reset("segment_id"); + }, + }); +}; diff --git a/resources/js/Pages/FieldJob/Index.vue b/resources/js/Pages/FieldJob/Index.vue index fc72575..e4d31e6 100644 --- a/resources/js/Pages/FieldJob/Index.vue +++ b/resources/js/Pages/FieldJob/Index.vue @@ -1,7 +1,7 @@ - + diff --git a/resources/js/Pages/Phone/Index.vue b/resources/js/Pages/Phone/Index.vue index 7acc7f5..7d4f3b6 100644 --- a/resources/js/Pages/Phone/Index.vue +++ b/resources/js/Pages/Phone/Index.vue @@ -53,33 +53,34 @@ function formatAmount(val) {
    - - + +
    diff --git a/resources/js/Pages/Segments/Index.vue b/resources/js/Pages/Segments/Index.vue new file mode 100644 index 0000000..c8236e3 --- /dev/null +++ b/resources/js/Pages/Segments/Index.vue @@ -0,0 +1,107 @@ + + + diff --git a/resources/js/Pages/Segments/Show.vue b/resources/js/Pages/Segments/Show.vue new file mode 100644 index 0000000..18aad8e --- /dev/null +++ b/resources/js/Pages/Segments/Show.vue @@ -0,0 +1,156 @@ + + + diff --git a/routes/web.php b/routes/web.php index 5d8e45c..9d91601 100644 --- a/routes/web.php +++ b/routes/web.php @@ -157,6 +157,7 @@ Route::delete('client-cases/{client_case:uuid}/objects/{id}', [CaseObjectController::class, 'destroy'])->name('clientCase.object.delete'); // client-case / activity Route::post('client-cases/{client_case:uuid}/activity', [ClientCaseContoller::class, 'storeActivity'])->name('clientCase.activity.store'); + Route::delete('client-cases/{client_case:uuid}/activity/{activity}', [ClientCaseContoller::class, 'deleteActivity'])->name('clientCase.activity.delete'); // client-case / segments Route::post('client-cases/{client_case:uuid}/segments', [ClientCaseContoller::class, 'attachSegment'])->name('clientCase.segments.attach'); // client-case / documents @@ -192,6 +193,10 @@ Route::delete('settings/actions/{id}', [WorkflowController::class, 'destroyAction'])->name('settings.actions.destroy'); Route::delete('settings/decisions/{id}', [WorkflowController::class, 'destroyDecision'])->name('settings.decisions.destroy'); + // segments index overview + Route::get('segments', [SegmentController::class, 'index'])->name('segments.index'); + Route::get('segments/{segment}', [SegmentController::class, 'show'])->name('segments.show'); + // imports Route::get('imports/create', [ImportController::class, 'create'])->name('imports.create'); Route::get('imports', [ImportController::class, 'index'])->name('imports.index');