close #3214 Enhancement: Document list page add default tab feature

This commit is contained in:
Cüneyt Şentürk 2024-09-25 09:02:52 +01:00
parent 3f93f53a0b
commit 11e681ba32
9 changed files with 241 additions and 8 deletions

View File

@ -100,6 +100,20 @@ abstract class Controller extends BaseController
public function setActiveTabForDocuments(): void
{
// Added this method to set the active tab for documents
if (! request()->has('list_records') && ! request()->has('search')) {
$tab_pins = setting('favorites.tab.' . user()->id, []);
$tab_pins = json_decode($tab_pins, true);
if (! empty($tab_pins) && ! empty($tab_pins[$this->type])) {
$data = config('type.document.' . $this->type . '.route.params.' . $tab_pins[$this->type]);
if (! empty($data)) {
request()->merge($data);
}
}
}
if (request()->get('list_records') == 'all') {
return;
}

View File

@ -567,10 +567,24 @@ abstract class Index extends Component
$status = $this->getSearchStringValue('status');
if ($status == 'draft') {
$unpaid = str_replace('status:', '', config('type.document.' . $type . '.route.params.unpaid.search'));
if ($status == $unpaid) {
return 'unpaid';
}
$draft = str_replace('status:', '', config('type.document.' . $type . '.route.params.draft.search'));
if ($status == $draft) {
return 'draft';
}
$suffix = $this->getTabActiveFromSetting($type);
if (! empty($suffix)) {
return $suffix;
}
return 'unpaid';
}

View File

@ -0,0 +1,96 @@
<?php
namespace App\Http\Livewire\Tab;
use Illuminate\Contracts\View\View;
use Livewire\Component;
class Pin extends Component
{
public $id;
public $type;
public $tab;
public $pinned = false;
protected $listeners = [
'addedPin' => 'render',
'removedPin' => 'render',
];
public function render(): View
{
$this->pinned = false;
$pins = setting('favorites.tab.' . user()->id, []);
if (! empty($pins) && ! $this->pinned) {
$pins = json_decode($pins, true);
$type_pinned = $pins[$this->type] ?? null;
if (isset($pins[$this->type]) && $this->tab == $type_pinned) {
$this->pinned = true;
}
}
return view('livewire.tab.pin');
}
public function changeStatus($tab)
{
if ($this->pinned) {
$this->removePin($tab);
} else {
$this->addPin($tab);
}
}
public function addPin($tab)
{
$pins = setting('favorites.tab.' . user()->id, []);
if (!empty($pins)) {
$pins = json_decode($pins, true);
}
$type_pinned = $pins[$this->type] ?? null;
if ($this->tab == $type_pinned) {
return;
}
$pins[$this->type] = $tab;
$this->pinned = true;
setting(['favorites.tab.' . user()->id => json_encode($pins)])->save();
$this->dispatch('addedPin');
}
public function removePin($tab)
{
$pins = setting('favorites.tab.' . user()->id, []);
if (!empty($pins)) {
$pins = json_decode($pins, true);
}
foreach ($pins as $key => $pinned_id) {
if ($pinned_id != $tab) {
continue;
}
unset($pins[$key]);
$this->pinned = false;
break;
}
setting(['favorites.tab.' . user()->id => json_encode($pins)])->save();
$this->dispatch('removedPin');
}
}

View File

@ -214,6 +214,19 @@ trait ViewComponents
return $script_key;
}
public function getTabActiveFromSetting($type)
{
$tabs = setting('favorites.tab.' . user()->id, []);
if (empty($tabs)) {
return false;
}
$tabs = json_decode($tabs, true);
return $tabs[$type] ?? false;
}
protected function getTextPage($type, $textPage)
{
if (! empty($textPage)) {

View File

@ -113,6 +113,7 @@ return [
'params' => [
'unpaid' => ['search' => 'status:sent,viewed,partial'],
'draft' => ['search' => 'status:draft'],
'all' => ['list_records' => 'all'],
],
],
'permission' => [
@ -218,6 +219,7 @@ return [
'params' => [
'unpaid' => ['search' => 'status:received,partial'],
'draft' => ['search' => 'status:draft'],
'all' => ['list_records' => 'all'],
],
],
'permission' => [

View File

@ -316,6 +316,11 @@ return [
'custom' => 'Custom',
],
'pin_text' => [
'pin_tab' => 'Pin default tab',
'unpin_tab' => 'Unpin default tab',
],
'empty' => [
'documentation' => 'Check out the <a href=":url" target="_blank" class="text-green bg-no-repeat bg-0-2 bg-0-full hover:bg-full-2 bg-gradient-to-b from-transparent to-green transition-backgroundSize">documentation</a> for more details.',
'items' => 'Items can be products or services. You can use items when creating invoices and bills to have the price, tax etc fields populated.',

View File

@ -5,26 +5,59 @@
<x-index.container>
@if (! $withoutTabs)
<x-tabs active="{{ $tabActive }}">
<x-tabs active="{{ $tabActive }}" id="tabs-{{ $type }}">
<x-slot name="navs">
@stack('document_nav_start')
@if ($tabActive == $type . '-unpaid')
<x-tabs.nav id="{{ $type . '-unpaid' }}" name="{{ trans('documents.statuses.unpaid') }}" active />
<x-tabs.nav-pin
id="{{ $type . '-unpaid' }}"
name="{{ trans('documents.statuses.unpaid') }}"
type="{{ $type }}"
tab="unpaid"
/>
@else
<x-tabs.nav-link id="{{ $type . '-unpaid' }}" name="{{ trans('documents.statuses.unpaid') }}" href="{{ route($routeTabDocument) }}" />
<x-tabs.nav-pin
id="{{ $type . '-unpaid' }}"
href="{{ route($routeTabDocument, $routeParamsTabUnpaid) }}"
name="{{ trans('documents.statuses.unpaid') }}"
type="{{ $type }}"
tab="unpaid"
/>
@endif
@if ($tabActive == $type . '-draft')
<x-tabs.nav id="{{ $type . '-draft' }}" name="{{ trans('documents.statuses.draft') }}" active />
<x-tabs.nav-pin
id="{{ $type . '-draft' }}"
name="{{ trans('documents.statuses.draft') }}"
type="{{ $type }}"
tab="draft"
/>
@else
<x-tabs.nav-link id="{{ $type . '-draft' }}" name="{{ trans('documents.statuses.draft') }}" href="{{ route($routeTabDocument, $routeParamsTabDraft) }}" />
<x-tabs.nav-pin
id="{{ $type . '-draft' }}"
href="{{ route($routeTabDocument, $routeParamsTabDraft) }}"
name="{{ trans('documents.statuses.draft') }}"
type="{{ $type }}"
tab="draft"
/>
@endif
@if ($tabActive == $type . '-all')
<x-tabs.nav id="{{ $type . '-all' }}" name="{{ trans('general.all_type', ['type' => trans_choice($textTabDocument, 2)]) }}" active />
<x-tabs.nav-pin
id="{{ $type . '-all' }}"
name="{{ trans('general.all_type', ['type' => trans_choice($textTabDocument, 2)]) }}"
type="{{ $type }}"
tab="all"
/>
@else
<x-tabs.nav-link id="{{ $type . '-all' }}" name="{{ trans('general.all_type', ['type' => trans_choice($textTabDocument, 2)]) }}" href="{{ route($routeTabDocument, ['list_records' => 'all']) }}" />
<x-tabs.nav-pin
id="{{ $type . '-all' }}"
href="{{ route($routeTabDocument, ['list_records' => 'all']) }}"
name="{{ trans('general.all_type', ['type' => trans_choice($textTabDocument, 2)]) }}"
type="{{ $type }}"
tab="all"
/>
@endif
@stack('document_nav_end')

View File

@ -0,0 +1,21 @@
@props(['id', 'name', 'href', 'active', 'type', 'tab'])
@if (empty($href))
<x-tabs.nav :id="$id" :active="$active ?? false">
<div class="flex items-center">
{{ $name }}
<livewire:tab.pin :type="$type" :id="$id" :tab="$tab" :pinned="$active ?? false" />
</div>
</x-tabs.nav>
@else
<x-tabs.nav-link :id="$id" :href="$href" :active="$active ?? false">
<div class="flex items-center">
<a href="{{ $href }}">
{{ $name }}
</a>
<livewire:tab.pin :type="$type" :id="$id" :tab="$tab" :pinned="$active ?? false" />
</div>
</x-tabs.nav-link>
@endif

View File

@ -0,0 +1,35 @@
<button class="w-8 h-8 flex items-center justify-center px-2 py-2 rounded-xl text-purple text-sm font-medium leading-6"
data-tooltip-target="{{ $id }}-pin"
data-tooltip-placement="top"
>
<span
id="{{ $pinned ? 'index-line-actions-unpin-tab-' . $id : 'index-line-actions-pin-tab-' . $id }}"
@class([
'text-sm transform rotate-45 transition-all',
'material-icons-outlined hover:scale-125' => ($pinned) ? false : true,
'material-icons' => (! $pinned) ? false : true,
])
wire:click="changeStatus('{{ $tab }}')"
>push_pin
</span>
@if ($pinned)
<div
id="{{ $id }}-pin"
role="tooltip"
class="inline-block absolute invisible z-20 py-1 px-2 text-sm font-medium text-gray-900 bg-white rounded-lg border border-gray-200 shadow-sm whitespace-nowrap opacity-0"
>
{{ trans('general.pin_text.unpin_tab') }}
<div class="absolute w-2 h-2 before:absolute before:w-2 before:h-2 before:bg-white before:border-gray-200 before:transform before:rotate-45 before:border -bottom-1 before:border-t-0 before:border-l-0 border-gray-200" data-popper-top></div>
</div>
@else
<div
id="{{ $id }}-pin"
role="tooltip"
class=" inline-block absolute invisible z-20 py-1 px-2 text-sm font-medium text-gray-900 bg-white rounded-lg border border-gray-200 shadow-sm whitespace-nowrap opacity-0"
>
{{ trans('general.pin_text.pin_tab') }}
<div class="absolute w-2 h-2 w-auto before:absolute before:w-2 before:h-2 before:bg-white before:border-gray-200 before:transform before:rotate-45 before:border -bottom-1 before:border-t-0 before:border-l-0 border-gray-200" data-popper-top></div>
</div>
@endif
</button>