Improved category types
This commit is contained in:
parent
2c4d52b15e
commit
6df965c930
|
|
@ -5,13 +5,14 @@ namespace App\Abstracts\Listeners;
|
||||||
use App\Models\Banking\Account;
|
use App\Models\Banking\Account;
|
||||||
use App\Models\Common\Contact;
|
use App\Models\Common\Contact;
|
||||||
use App\Models\Setting\Category;
|
use App\Models\Setting\Category;
|
||||||
|
use App\Traits\Categories;
|
||||||
use App\Traits\Contacts;
|
use App\Traits\Contacts;
|
||||||
use App\Traits\DateTime;
|
use App\Traits\DateTime;
|
||||||
use App\Traits\SearchString;
|
use App\Traits\SearchString;
|
||||||
|
|
||||||
abstract class Report
|
abstract class Report
|
||||||
{
|
{
|
||||||
use Contacts, DateTime, SearchString;
|
use Categories, Contacts, DateTime, SearchString;
|
||||||
|
|
||||||
protected $classes = [];
|
protected $classes = [];
|
||||||
|
|
||||||
|
|
@ -90,22 +91,24 @@ abstract class Report
|
||||||
|
|
||||||
public function getItemCategories($limit = false)
|
public function getItemCategories($limit = false)
|
||||||
{
|
{
|
||||||
return $this->getCategories('item', $limit);
|
return $this->getCategories($this->getItemCategoryTypes(), $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getIncomeCategories($limit = false)
|
public function getIncomeCategories($limit = false)
|
||||||
{
|
{
|
||||||
return $this->getCategories('income', $limit);
|
return $this->getCategories($this->getIncomeCategoryTypes(), $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExpenseCategories($limit = false)
|
public function getExpenseCategories($limit = false)
|
||||||
{
|
{
|
||||||
return $this->getCategories('expense', $limit);
|
return $this->getCategories($this->getExpenseCategoryTypes(), $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getIncomeExpenseCategories($limit = false)
|
public function getIncomeExpenseCategories($limit = false)
|
||||||
{
|
{
|
||||||
return $this->getCategories(['income', 'expense'], $limit);
|
$types = array_merge($this->getIncomeCategoryTypes(), $this->getExpenseCategoryTypes());
|
||||||
|
|
||||||
|
return $this->getCategories($types, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCategories($types, $limit = false)
|
public function getCategories($types, $limit = false)
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,12 @@ use App\Abstracts\Http\SettingController;
|
||||||
use App\Models\Banking\Account;
|
use App\Models\Banking\Account;
|
||||||
use App\Models\Setting\Category;
|
use App\Models\Setting\Category;
|
||||||
use App\Models\Setting\Tax;
|
use App\Models\Setting\Tax;
|
||||||
|
use App\Traits\Categories;
|
||||||
|
|
||||||
class Defaults extends SettingController
|
class Defaults extends SettingController
|
||||||
{
|
{
|
||||||
|
use Categories;
|
||||||
|
|
||||||
public function edit()
|
public function edit()
|
||||||
{
|
{
|
||||||
$accounts = Account::enabled()->orderBy('name')->get()->pluck('title', 'id');
|
$accounts = Account::enabled()->orderBy('name')->get()->pluck('title', 'id');
|
||||||
|
|
@ -39,11 +42,16 @@ class Defaults extends SettingController
|
||||||
|
|
||||||
$taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
|
$taxes = Tax::enabled()->orderBy('name')->get()->pluck('title', 'id');
|
||||||
|
|
||||||
|
$income_category_types = $this->getIncomeCategoryTypes('string');
|
||||||
|
$expense_category_types = $this->getExpenseCategoryTypes('string');
|
||||||
|
|
||||||
return view('settings.default.edit', compact(
|
return view('settings.default.edit', compact(
|
||||||
'accounts',
|
'accounts',
|
||||||
'sales_categories',
|
'sales_categories',
|
||||||
'purchases_categories',
|
'purchases_categories',
|
||||||
'taxes',
|
'taxes',
|
||||||
|
'income_category_types',
|
||||||
|
'expense_category_types',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ class AddExpenseCategories extends Listener
|
||||||
|
|
||||||
// send true for add limit on search and filter..
|
// send true for add limit on search and filter..
|
||||||
$event->class->filters['categories'] = $this->getExpenseCategories(true);
|
$event->class->filters['categories'] = $this->getExpenseCategories(true);
|
||||||
$event->class->filters['routes']['categories'] = ['categories.index', 'search=type:expense enabled:1'];
|
$event->class->filters['routes']['categories'] = ['categories.index', 'search=type:' . $this->getExpenseCategoryTypes('string') . ' enabled:1'];
|
||||||
$event->class->filters['multiple']['categories'] = true;
|
$event->class->filters['multiple']['categories'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ class AddIncomeCategories extends Listener
|
||||||
|
|
||||||
// send true for add limit on search and filter..
|
// send true for add limit on search and filter..
|
||||||
$event->class->filters['categories'] = $this->getIncomeCategories(true);
|
$event->class->filters['categories'] = $this->getIncomeCategories(true);
|
||||||
$event->class->filters['routes']['categories'] = ['categories.index', 'search=type:income enabled:1'];
|
$event->class->filters['routes']['categories'] = ['categories.index', 'search=type:' . $this->getIncomeCategoryTypes('string') . ' enabled:1'];
|
||||||
$event->class->filters['multiple']['categories'] = true;
|
$event->class->filters['multiple']['categories'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class AddIncomeExpenseCategories extends Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
$event->class->filters['categories'] = $this->getIncomeExpenseCategories(true);
|
$event->class->filters['categories'] = $this->getIncomeExpenseCategories(true);
|
||||||
$event->class->filters['routes']['categories'] = ['categories.index', 'search=type:income,expense enabled:1'];
|
$event->class->filters['routes']['categories'] = ['categories.index', 'search=type:' . implode(',', array_merge($this->getIncomeCategoryTypes(), $this->getExpenseCategoryTypes())) . ' enabled:1'];
|
||||||
$event->class->filters['multiple']['categories'] = true;
|
$event->class->filters['multiple']['categories'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ class AddIncomeExpenseCategories extends Listener
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$categories = Category::type(['income', 'expense'])->orderBy('name')->get();
|
$categories = Category::type(array_merge($this->getIncomeCategoryTypes(), $this->getExpenseCategoryTypes()))->orderBy('name')->get();
|
||||||
$rows = $categories->pluck('name', 'id')->toArray();
|
$rows = $categories->pluck('name', 'id')->toArray();
|
||||||
|
|
||||||
$this->setRowNamesAndValuesForCategories($event, $rows, $categories);
|
$this->setRowNamesAndValuesForCategories($event, $rows, $categories);
|
||||||
|
|
@ -83,10 +83,12 @@ class AddIncomeExpenseCategories extends Listener
|
||||||
{
|
{
|
||||||
foreach ($event->class->dates as $date) {
|
foreach ($event->class->dates as $date) {
|
||||||
foreach ($event->class->tables as $table_key => $table_name) {
|
foreach ($event->class->tables as $table_key => $table_name) {
|
||||||
|
$table_keys = $table_key == Category::INCOME_TYPE ? $this->getIncomeCategoryTypes() : $this->getExpenseCategoryTypes();
|
||||||
|
|
||||||
foreach ($rows as $id => $name) {
|
foreach ($rows as $id => $name) {
|
||||||
$category = $categories->where('id', $id)->first();
|
$category = $categories->where('id', $id)->first();
|
||||||
|
|
||||||
if ($category->type != $table_key) {
|
if (!in_array($category->type, $table_keys)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,10 +102,12 @@ class AddIncomeExpenseCategories extends Listener
|
||||||
public function setTreeNodesForCategories($event, $nodes, $categories)
|
public function setTreeNodesForCategories($event, $nodes, $categories)
|
||||||
{
|
{
|
||||||
foreach ($event->class->tables as $table_key => $table_name) {
|
foreach ($event->class->tables as $table_key => $table_name) {
|
||||||
|
$table_keys = $table_key == Category::INCOME_TYPE ? $this->getIncomeCategoryTypes() : $this->getExpenseCategoryTypes();
|
||||||
|
|
||||||
foreach ($nodes as $id => $node) {
|
foreach ($nodes as $id => $node) {
|
||||||
$category = $categories->where('id', $id)->first();
|
$category = $categories->where('id', $id)->first();
|
||||||
|
|
||||||
if ($category->type != $table_key) {
|
if (!in_array($category->type, $table_keys)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -616,9 +616,10 @@ class Company extends Eloquent implements Ownable
|
||||||
setting()->forgetAll();
|
setting()->forgetAll();
|
||||||
setting()->load(true);
|
setting()->load(true);
|
||||||
|
|
||||||
// Override settings and currencies
|
// Override settings, currencies, and category types
|
||||||
Overrider::load('settings');
|
Overrider::load('settings');
|
||||||
Overrider::load('currencies');
|
Overrider::load('currencies');
|
||||||
|
Overrider::load('categoryTypes');
|
||||||
|
|
||||||
event(new CompanyMadeCurrent($this));
|
event(new CompanyMadeCurrent($this));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,97 @@ use Illuminate\Support\Str;
|
||||||
|
|
||||||
trait Categories
|
trait Categories
|
||||||
{
|
{
|
||||||
public function getCategoryTypes(bool $translate = true): array
|
public function isIncomeCategory(): bool
|
||||||
|
{
|
||||||
|
$type = $this->type ?? $this->category->type ?? $this->model->type ?? Category::INCOME_TYPE;
|
||||||
|
|
||||||
|
return in_array($type, $this->getIncomeCategoryTypes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isExpenseCategory(): bool
|
||||||
|
{
|
||||||
|
$type = $this->type ?? $this->category->type ?? $this->model->type ?? Category::EXPENSE_TYPE;
|
||||||
|
|
||||||
|
return in_array($type, $this->getExpenseCategoryTypes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isItemCategory(): bool
|
||||||
|
{
|
||||||
|
$type = $this->type ?? $this->category->type ?? $this->model->type ?? Category::ITEM_TYPE;
|
||||||
|
|
||||||
|
return in_array($type, $this->getItemCategoryTypes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isOtherCategory(): bool
|
||||||
|
{
|
||||||
|
$type = $this->type ?? $this->category->type ?? $this->model->type ?? Category::OTHER_TYPE;
|
||||||
|
|
||||||
|
return in_array($type, $this->getOtherCategoryTypes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIncomeCategoryTypes(string $return = 'array'): string|array
|
||||||
|
{
|
||||||
|
return $this->getCategoryTypesByIndex(Category::INCOME_TYPE, $return);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExpenseCategoryTypes(string $return = 'array'): string|array
|
||||||
|
{
|
||||||
|
return $this->getCategoryTypesByIndex(Category::EXPENSE_TYPE, $return);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getItemCategoryTypes(string $return = 'array'): string|array
|
||||||
|
{
|
||||||
|
return $this->getCategoryTypesByIndex(Category::ITEM_TYPE, $return);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOtherCategoryTypes(string $return = 'array'): string|array
|
||||||
|
{
|
||||||
|
return $this->getCategoryTypesByIndex(Category::OTHER_TYPE, $return);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCategoryTypesByIndex(string $index, string $return = 'array'): string|array
|
||||||
|
{
|
||||||
|
$types = (string) setting('category.type.' . $index);
|
||||||
|
|
||||||
|
return ($return == 'array') ? explode(',', $types) : $types;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addIncomeCategoryType(string $new_type): void
|
||||||
|
{
|
||||||
|
$this->addCategoryType($new_type, Category::INCOME_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addExpenseCategoryType(string $new_type): void
|
||||||
|
{
|
||||||
|
$this->addCategoryType($new_type, Category::EXPENSE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addItemCategoryType(string $new_type): void
|
||||||
|
{
|
||||||
|
$this->addCategoryType($new_type, Category::ITEM_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addOtherCategoryType(string $new_type): void
|
||||||
|
{
|
||||||
|
$this->addCategoryType($new_type, Category::OTHER_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addCategoryType(string $new_type, string $index): void
|
||||||
|
{
|
||||||
|
$types = !empty(setting('category.type.' . $index)) ? explode(',', setting('category.type.' . $index)) : [];
|
||||||
|
|
||||||
|
if (in_array($new_type, $types)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$types[] = $new_type;
|
||||||
|
|
||||||
|
setting([
|
||||||
|
'category.type.' . $index => implode(',', $types),
|
||||||
|
])->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCategoryTypes(bool $translate = true, bool $group = false): array
|
||||||
{
|
{
|
||||||
$types = [];
|
$types = [];
|
||||||
$configs = config('type.category');
|
$configs = config('type.category');
|
||||||
|
|
@ -22,12 +112,48 @@ trait Categories
|
||||||
$name = $attr['alias'] . '::' . $name;
|
$name = $attr['alias'] . '::' . $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
$types[$type] = $translate ? trans_choice($name, 1) : $name;
|
if ($group) {
|
||||||
|
$group_key = $attr['group'] ?? $type;
|
||||||
|
$types[$group_key][$type] = $translate ? trans_choice($name, 1) : $name;
|
||||||
|
} else {
|
||||||
|
$types[$type] = $translate ? trans_choice($name, 1) : $name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $types;
|
return $types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getCategoryTabs(): array
|
||||||
|
{
|
||||||
|
$tabs = [];
|
||||||
|
$configs = config('type.category');
|
||||||
|
|
||||||
|
foreach ($configs as $type => $attr) {
|
||||||
|
$tab_key = 'categories-' . ($attr['group'] ?? $type);
|
||||||
|
|
||||||
|
if (isset($tabs[$tab_key])) {
|
||||||
|
$tabs[$tab_key]['key'] .= ',' . $type;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plural_type = Str::plural($attr['group'] ?? $type);
|
||||||
|
|
||||||
|
$name = $attr['translation']['prefix'] . '.' . $plural_type;
|
||||||
|
|
||||||
|
if (!empty($attr['alias'])) {
|
||||||
|
$name = $attr['alias'] . '::' . $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tabs[$tab_key] = [
|
||||||
|
'key' => $type,
|
||||||
|
'name' => trans_choice($name, 2),
|
||||||
|
'show_code' => $attr['show_code'] ?? false,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tabs;
|
||||||
|
}
|
||||||
|
|
||||||
public function getCategoryWithoutChildren(int $id): mixed
|
public function getCategoryWithoutChildren(int $id): mixed
|
||||||
{
|
{
|
||||||
return Category::getWithoutChildren()->find($id);
|
return Category::getWithoutChildren()->find($id);
|
||||||
|
|
@ -36,7 +162,7 @@ trait Categories
|
||||||
public function getTransferCategoryId(): mixed
|
public function getTransferCategoryId(): mixed
|
||||||
{
|
{
|
||||||
// 1 hour set cache for same query
|
// 1 hour set cache for same query
|
||||||
return Cache::remember('transferCategoryId', 60, function () {
|
return Cache::remember('transferCategoryId.' . company_id(), 60, function () {
|
||||||
return Category::other()->pluck('id')->first();
|
return Category::other()->pluck('id')->first();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -62,4 +188,16 @@ trait Categories
|
||||||
|
|
||||||
return $ids;
|
return $ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds existing maximum code and increase it
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getNextCategoryCode()
|
||||||
|
{
|
||||||
|
return Category::isNotSubCategory()->get(['code'])->reject(function ($category) {
|
||||||
|
return !preg_match('/^[0-9]*$/', $category->code);
|
||||||
|
})->max('code') + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace App\Traits;
|
||||||
|
|
||||||
use Akaunting\Module\Module;
|
use Akaunting\Module\Module;
|
||||||
use App\Events\Common\BulkActionsAdding;
|
use App\Events\Common\BulkActionsAdding;
|
||||||
|
use App\Models\Setting\Category;
|
||||||
use App\Traits\Modules;
|
use App\Traits\Modules;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
@ -188,19 +189,19 @@ trait ViewComponents
|
||||||
case 'bill':
|
case 'bill':
|
||||||
case 'expense':
|
case 'expense':
|
||||||
case 'purchase':
|
case 'purchase':
|
||||||
$category_type = 'expense';
|
$category_type = Category::EXPENSE_TYPE;
|
||||||
break;
|
break;
|
||||||
case 'item':
|
case 'item':
|
||||||
$category_type = 'item';
|
$category_type = Category::ITEM_TYPE;
|
||||||
break;
|
break;
|
||||||
case 'other':
|
case 'other':
|
||||||
$category_type = 'other';
|
$category_type = Category::OTHER_TYPE;
|
||||||
break;
|
break;
|
||||||
case 'transfer':
|
case 'transfer':
|
||||||
$category_type = 'transfer';
|
$category_type = 'transfer';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$category_type = 'income';
|
$category_type = Category::INCOME_TYPE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@
|
||||||
namespace App\Utilities;
|
namespace App\Utilities;
|
||||||
|
|
||||||
use Akaunting\Money\Money;
|
use Akaunting\Money\Money;
|
||||||
|
use App\Models\Setting\Category;
|
||||||
use App\Models\Setting\Currency;
|
use App\Models\Setting\Currency;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class Overrider
|
class Overrider
|
||||||
{
|
{
|
||||||
|
|
@ -60,7 +62,7 @@ class Overrider
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set locale for Money package
|
// Set locale for Money package
|
||||||
Money::setLocale(app()->getLocale());
|
Money::setLocale(app()->getLocale());
|
||||||
|
|
||||||
// Money
|
// Money
|
||||||
config(['money.defaults.currency' => setting('default.currency')]);
|
config(['money.defaults.currency' => setting('default.currency')]);
|
||||||
|
|
@ -71,6 +73,45 @@ class Overrider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function loadCategoryTypes()
|
||||||
|
{
|
||||||
|
$category = new Category;
|
||||||
|
|
||||||
|
$income_types = $category->getIncomeCategoryTypes('string');
|
||||||
|
$expense_types = $category->getExpenseCategoryTypes('string');
|
||||||
|
$item_types = $category->getItemCategoryTypes('string');
|
||||||
|
$other_types = $category->getOtherCategoryTypes('string');
|
||||||
|
|
||||||
|
$search_string = config('search-string');
|
||||||
|
|
||||||
|
foreach ($search_string as $model => &$model_config) {
|
||||||
|
$route = $model_config['columns']['category_id']['route'] ?? null;
|
||||||
|
|
||||||
|
// Only update category_id routes that point to categories.index
|
||||||
|
if (!is_array($route) || ($route[0] ?? '') !== 'categories.index' || !isset($route[1])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Longest match first (income,expense must come before income)
|
||||||
|
$replacements = [
|
||||||
|
'type:' . Category::INCOME_TYPE . ',' . Category::EXPENSE_TYPE => 'type:' . $income_types . ',' . $expense_types,
|
||||||
|
'type:' . Category::INCOME_TYPE => 'type:' . $income_types,
|
||||||
|
'type:' . Category::EXPENSE_TYPE => 'type:' . $expense_types,
|
||||||
|
'type:' . Category::ITEM_TYPE => 'type:' . $item_types,
|
||||||
|
'type:' . Category::OTHER_TYPE => 'type:' . $other_types,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($replacements as $search => $replace) {
|
||||||
|
if (Str::contains($route[1], $search)) {
|
||||||
|
$model_config['columns']['category_id']['route'][1] = Str::replace($search, $replace, $route[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config(['search-string' => $search_string]);
|
||||||
|
}
|
||||||
|
|
||||||
protected static function loadCurrencies()
|
protected static function loadCurrencies()
|
||||||
{
|
{
|
||||||
$currencies = Currency::all();
|
$currencies = Currency::all();
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,15 @@ namespace App\View\Components\Form\Group;
|
||||||
|
|
||||||
use App\Abstracts\View\Components\Form;
|
use App\Abstracts\View\Components\Form;
|
||||||
use App\Models\Setting\Category as Model;
|
use App\Models\Setting\Category as Model;
|
||||||
|
use App\Traits\Categories;
|
||||||
|
use App\Traits\Modules;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
class Category extends Form
|
class Category extends Form
|
||||||
{
|
{
|
||||||
public $type = 'income';
|
use Categories, Modules;
|
||||||
|
|
||||||
|
public $type = Model::INCOME_TYPE;
|
||||||
|
|
||||||
public $path;
|
public $path;
|
||||||
|
|
||||||
|
|
@ -15,6 +20,14 @@ class Category extends Form
|
||||||
|
|
||||||
public $categories;
|
public $categories;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
public $group;
|
||||||
|
|
||||||
|
public $option_field = [
|
||||||
|
'key' => 'id',
|
||||||
|
'value' => 'name',
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the view / contents that represent the component.
|
* Get the view / contents that represent the component.
|
||||||
*
|
*
|
||||||
|
|
@ -26,26 +39,133 @@ class Category extends Form
|
||||||
$this->name = 'category_id';
|
$this->name = 'category_id';
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->path = route('modals.categories.create', ['type' => $this->type]);
|
switch ($this->type) {
|
||||||
$this->remoteAction = route('categories.index', ['search' => 'type:' . $this->type . ' enabled:1']);
|
case Model::INCOME_TYPE:
|
||||||
|
$types = $this->getIncomeCategoryTypes();
|
||||||
|
break;
|
||||||
|
case Model::EXPENSE_TYPE:
|
||||||
|
$types = $this->getExpenseCategoryTypes();
|
||||||
|
break;
|
||||||
|
case Model::ITEM_TYPE:
|
||||||
|
$types = $this->getItemCategoryTypes();
|
||||||
|
break;
|
||||||
|
case Model::OTHER_TYPE:
|
||||||
|
$types = $this->getOtherCategoryTypes();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$types = [$this->type];
|
||||||
|
}
|
||||||
|
|
||||||
$this->categories = Model::type($this->type)->enabled()->orderBy('name')->take(setting('default.select_limit'))->get();
|
$this->path = route('modals.categories.create', ['type' => $this->type]);
|
||||||
|
$this->remoteAction = route('categories.index', ['search' => 'type:' . implode(',', $types) . ' enabled:1']);
|
||||||
|
|
||||||
|
$typeLabels = collect($this->getCategoryTypes())->only($types)->all();
|
||||||
|
|
||||||
|
$is_code = false;
|
||||||
|
|
||||||
|
foreach (config('type.category', []) as $type => $config) {
|
||||||
|
if (! in_array($type, $types)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($config['hide']) || ! in_array('code', $config['hide'])) {
|
||||||
|
$is_code = true;
|
||||||
|
$this->group = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_by = $is_code ? 'code' : 'name';
|
||||||
|
|
||||||
|
if ($this->group) {
|
||||||
|
$this->option_field = [
|
||||||
|
'key' => 'id',
|
||||||
|
'value' => 'title',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = Model::type($types);
|
||||||
|
|
||||||
|
$query->enabled()
|
||||||
|
->orderBy($order_by);
|
||||||
|
|
||||||
|
if (! $this->group) {
|
||||||
|
$query->take(setting('default.select_limit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->categories = $query->get();
|
||||||
|
|
||||||
|
if ($this->group) {
|
||||||
|
$groups = [];
|
||||||
|
|
||||||
|
foreach ($this->categories as $category) {
|
||||||
|
$group = $typeLabels[$category->type] ?? trans_choice('general.others', 1);
|
||||||
|
|
||||||
|
$category->title = ($category->code ? $category->code . ' - ' : '') . $category->name;
|
||||||
|
$category->group = $group;
|
||||||
|
|
||||||
|
$groups[$group][$category->id] = $category;
|
||||||
|
}
|
||||||
|
|
||||||
|
ksort($groups);
|
||||||
|
|
||||||
|
$this->categories = $groups;
|
||||||
|
}
|
||||||
|
|
||||||
$model = $this->getParentData('model');
|
$model = $this->getParentData('model');
|
||||||
|
$selected_category = null;
|
||||||
|
|
||||||
|
$categoryExists = function ($categoryId): bool {
|
||||||
|
if (! $this->group) {
|
||||||
|
return $this->categories->contains(function ($category) use ($categoryId) {
|
||||||
|
return (int) $category->id === (int) $categoryId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->categories as $group_categories) {
|
||||||
|
foreach ($group_categories as $category) {
|
||||||
|
if ((int) $category->id === (int) $categoryId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
$appendCategory = function ($category) use ($typeLabels): void {
|
||||||
|
if (empty($category)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$category->title = ($category->code ? $category->code . ' - ' : '') . $category->name;
|
||||||
|
|
||||||
|
if (! $this->group) {
|
||||||
|
$this->categories->push($category);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$group = $typeLabels[$category->type] ?? trans_choice('general.others', 1);
|
||||||
|
|
||||||
|
if (! isset($this->categories[$group])) {
|
||||||
|
$this->categories[$group] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->categories[$group][$category->id] = $category;
|
||||||
|
|
||||||
|
ksort($this->categories);
|
||||||
|
};
|
||||||
|
|
||||||
$category_id = old('category.id', old('category_id', null));
|
$category_id = old('category.id', old('category_id', null));
|
||||||
|
|
||||||
if (! empty($category_id)) {
|
if (! empty($category_id)) {
|
||||||
$this->selected = $category_id;
|
$this->selected = $category_id;
|
||||||
|
|
||||||
$has_category = $this->categories->search(function ($category, int $key) use ($category_id) {
|
if (! $categoryExists($category_id)) {
|
||||||
return $category->id === $category_id;
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($has_category === false) {
|
|
||||||
$category = Model::find($category_id);
|
$category = Model::find($category_id);
|
||||||
|
|
||||||
$this->categories->push($category);
|
$appendCategory($category);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,15 +181,15 @@ class Category extends Form
|
||||||
$selected_category = Model::find($this->selected);
|
$selected_category = Model::find($this->selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (empty($selected_category) && ! empty($this->selected)) {
|
||||||
|
$selected_category = Model::find($this->selected);
|
||||||
|
}
|
||||||
|
|
||||||
if (! empty($selected_category)) {
|
if (! empty($selected_category)) {
|
||||||
$selected_category_id = $selected_category->id;
|
$selected_category_id = $selected_category->id;
|
||||||
|
|
||||||
$has_selected_category = $this->categories->search(function ($category, int $key) use ($selected_category_id) {
|
if (! $categoryExists($selected_category_id)) {
|
||||||
return $category->id === $selected_category_id;
|
$appendCategory($selected_category);
|
||||||
});
|
|
||||||
|
|
||||||
if ($has_selected_category === false) {
|
|
||||||
$this->categories->push($selected_category);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
:collapse-tags="collapse"
|
:collapse-tags="collapse"
|
||||||
:remote-method="remoteMethod"
|
:remote-method="remoteMethod"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
|
:class="[{ 'with-color-prefix': selectedOptionColor, 'with-icon-prefix': icon }]"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="loading"
|
v-if="loading"
|
||||||
|
|
@ -56,21 +57,24 @@
|
||||||
<div v-if="!loading && addNew.status && options.length == 0">
|
<div v-if="!loading && addNew.status && options.length == 0">
|
||||||
<el-option class="text-center" disabled :label="noDataText" value="value"></el-option>
|
<el-option class="text-center" disabled :label="noDataText" value="value"></el-option>
|
||||||
|
|
||||||
<ul class="el-scrollbar__view el-select-dropdown__list">
|
<li class="el-select-dropdown__item el-select__footer bg-purple sticky bottom-0">
|
||||||
<li class="el-select-dropdown__item el-select__footer bg-purple sticky bottom-0">
|
<div class="w-full flex items-center" @click="onAddItem">
|
||||||
<div class="w-full flex items-center" @click="onAddItem">
|
<span class="material-icons text-xl text-purple">add</span>
|
||||||
<span class="material-icons text-xl text-purple">add</span>
|
<span class="flex-1 font-bold text-purple">
|
||||||
<span class="flex-1 font-bold text-purple">
|
{{ addNew.text }}
|
||||||
{{ addNew.text }}
|
</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template slot="prefix">
|
<template slot="prefix">
|
||||||
<span class="el-input__suffix-inner el-select-icon">
|
<span class="aka-select-prefix">
|
||||||
<i :class="'select-icon-position el-input__icon fa fa-' + icon"></i>
|
<span
|
||||||
|
v-if="!isDropdownVisible && selectedOptionColor"
|
||||||
|
class="w-4 h-4 rounded-full mt-1 ml-2"
|
||||||
|
:style="{ backgroundColor: selectedOptionColor }"
|
||||||
|
></span>
|
||||||
|
<i v-if="icon" :class="'select-icon-position el-input__icon fa fa-' + icon"></i>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -141,12 +145,19 @@
|
||||||
|
|
||||||
<component v-bind:is="add_new_html" @submit="onSubmit" @cancel="onCancel"></component>
|
<component v-bind:is="add_new_html" @submit="onSubmit" @cancel="onCancel"></component>
|
||||||
|
|
||||||
<span slot="infoBlock" class="absolute right-8 top-3 bg-green text-white px-2 py-1 rounded-md text-xs" v-if="new_options[selected] || (sorted_options.length && sorted_options[sorted_options.length - 1].mark_new && sorted_options[sorted_options.length - 1].key == selected)">{{ addNew.new_text }}</span>
|
<span slot="infoBlock" class="absolute right-8 top-3 bg-green text-white px-2 py-1 rounded-md text-xs" v-if="!isDropdownVisible && (new_options[selected] || (sorted_options.length && sorted_options[sorted_options.length - 1].mark_new && sorted_options[sorted_options.length - 1].key == selected))">{{ addNew.new_text }}</span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
slot="infoBlock"
|
||||||
|
class="absolute right-8 top-4 rounded-md bg-gray-50 px-2 py-0.5 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"
|
||||||
|
v-if="!isDropdownVisible && group && selectedGroupLabel"
|
||||||
|
>
|
||||||
|
{{ selectedGroupLabel }}
|
||||||
|
</span>
|
||||||
|
|
||||||
<select :name="name" :id="name + '-' + _uid" class="hidden">
|
<select :name="name" :id="name + '-' + _uid" class="hidden">
|
||||||
<option v-for="option in sortedOptions" :key="option.key" :value="option.key">{{ option.value }}</option>
|
<option v-for="option in sortedOptions" :key="option.key" :value="option.key">{{ option.value }}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</base-input>
|
</base-input>
|
||||||
|
|
||||||
<span v-else>
|
<span v-else>
|
||||||
|
|
@ -159,6 +170,7 @@
|
||||||
:collapse-tags="collapse"
|
:collapse-tags="collapse"
|
||||||
:remote-method="remoteMethod"
|
:remote-method="remoteMethod"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
|
:class="[{ 'with-color-prefix': selectedOptionColor, 'with-icon-prefix': icon }]"
|
||||||
>
|
>
|
||||||
<div v-if="loading" class="el-select-dropdown__wrap" slot="empty">
|
<div v-if="loading" class="el-select-dropdown__wrap" slot="empty">
|
||||||
<p class="el-select-dropdown__empty pt-2 pb-0 loading">
|
<p class="el-select-dropdown__empty pt-2 pb-0 loading">
|
||||||
|
|
@ -185,21 +197,25 @@
|
||||||
|
|
||||||
<div v-if="!loading && addNew.status && options.length == 0">
|
<div v-if="!loading && addNew.status && options.length == 0">
|
||||||
<el-option class="text-center" disabled :label="noDataText" value="value"></el-option>
|
<el-option class="text-center" disabled :label="noDataText" value="value"></el-option>
|
||||||
<ul class="el-scrollbar__view el-select-dropdown__list">
|
|
||||||
<li class="el-select-dropdown__item el-select__footer bg-purple sticky bottom-0">
|
<li class="el-select-dropdown__item el-select__footer bg-purple sticky bottom-0">
|
||||||
<div class="w-full flex items-center" @click="onAddItem">
|
<div class="w-full flex items-center" @click="onAddItem">
|
||||||
<span class="material-icons text-xl text-purple">add</span>
|
<span class="material-icons text-xl text-purple">add</span>
|
||||||
<span class="flex-1 font-bold text-purple">
|
<span class="flex-1 font-bold text-purple">
|
||||||
{{ addNew.text }}
|
{{ addNew.text }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template slot="prefix">
|
<template slot="prefix">
|
||||||
<span class="el-input__suffix-inner el-select-icon">
|
<span class="aka-select-prefix">
|
||||||
<i :class="'select-icon-position el-input__icon fa fa-' + icon"></i>
|
<span
|
||||||
|
v-if="selectedOptionColor"
|
||||||
|
class="aka-select-prefix-dot"
|
||||||
|
:style="{ backgroundColor: selectedOptionColor }"
|
||||||
|
></span>
|
||||||
|
<i v-if="icon" :class="'select-icon-position el-input__icon fa fa-' + icon"></i>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -265,12 +281,19 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</el-option>
|
</el-option>
|
||||||
|
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|
||||||
<component v-bind:is="add_new_html" @submit="onSubmit" @cancel="onCancel"></component>
|
<component v-bind:is="add_new_html" @submit="onSubmit" @cancel="onCancel"></component>
|
||||||
|
|
||||||
<span slot="infoBlock" class="absolute right-8 top-3 bg-green text-white px-2 py-1 rounded-md text-xs" v-if="new_options[selected] || (sorted_options.length && sorted_options[sorted_options.length - 1].mark_new && sorted_options[sorted_options.length - 1].key == selected)">{{ addNew.new_text }}</span>
|
<span slot="infoBlock" class="absolute right-8 top-3 bg-green text-white px-2 py-1 rounded-md text-xs" v-if="!isDropdownVisible && (new_options[selected] || (sorted_options.length && sorted_options[sorted_options.length - 1].mark_new && sorted_options[sorted_options.length - 1].key == selected))">{{ addNew.new_text }}</span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
slot="infoBlock"
|
||||||
|
class="absolute right-8 top-4 rounded-md bg-gray-50 px-2 py-0.5 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"
|
||||||
|
v-if="!isDropdownVisible && group && selectedGroupLabel"
|
||||||
|
>
|
||||||
|
{{ selectedGroupLabel }}
|
||||||
|
</span>
|
||||||
|
|
||||||
<select :name="name" :id="name + '-' + _uid" v-model="selected" class="d-none">
|
<select :name="name" :id="name + '-' + _uid" v-model="selected" class="d-none">
|
||||||
<option v-for="option in sortedOptions" :key="option.key" :value="option.key">{{ option.value }}</option>
|
<option v-for="option in sortedOptions" :key="option.key" :value="option.key">{{ option.value }}</option>
|
||||||
|
|
@ -520,6 +543,7 @@ export default {
|
||||||
full_options:[],
|
full_options:[],
|
||||||
new_options: {},
|
new_options: {},
|
||||||
loading: false,
|
loading: false,
|
||||||
|
isDropdownVisible: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -549,6 +573,48 @@ export default {
|
||||||
|
|
||||||
return this.sorted_options;
|
return this.sorted_options;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
selectedGroupLabel() {
|
||||||
|
if (!this.group || !Array.isArray(this.sorted_options) || !this.sorted_options.length) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.multiple) {
|
||||||
|
if (!Array.isArray(this.selected) || !this.selected.length) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const labels = this.selected
|
||||||
|
.map(value => this.findGroupLabelByOptionKey(value))
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
return [...new Set(labels)].join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.findGroupLabelByOptionKey(this.selected);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedOptionColor() {
|
||||||
|
const selectedOption = this.getSelectedOptionData();
|
||||||
|
|
||||||
|
if (!selectedOption || typeof selectedOption !== 'object') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedOption.color_hex_code) {
|
||||||
|
return selectedOption.color_hex_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedOption.color_hex) {
|
||||||
|
return selectedOption.color_hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedOption.color && selectedOption.color.toString().startsWith('#')) {
|
||||||
|
return selectedOption.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -579,6 +645,78 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
getSelectedOptionData() {
|
||||||
|
const selectedKey = this.multiple
|
||||||
|
? (Array.isArray(this.selected) && this.selected.length ? this.selected[0] : null)
|
||||||
|
: this.selected;
|
||||||
|
|
||||||
|
if (selectedKey === null || selectedKey === undefined || selectedKey === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const foundOption = this.findOptionByKey(selectedKey);
|
||||||
|
|
||||||
|
if (!foundOption) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundOption.option ? foundOption.option : foundOption;
|
||||||
|
},
|
||||||
|
|
||||||
|
findOptionByKey(optionKey) {
|
||||||
|
const normalizedKey = optionKey.toString();
|
||||||
|
|
||||||
|
if (this.group) {
|
||||||
|
for (const groupOption of this.sorted_options) {
|
||||||
|
if (!Array.isArray(groupOption.value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const found = groupOption.value.find(option => option.key == normalizedKey);
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const found = this.sorted_options.find(option => option.key == normalizedKey);
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const foundInFullOptions = this.full_options.find(option => option.key == normalizedKey);
|
||||||
|
|
||||||
|
if (foundInFullOptions) {
|
||||||
|
return foundInFullOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
findGroupLabelByOptionKey(optionKey) {
|
||||||
|
if (optionKey === null || optionKey === undefined || optionKey === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedKey = optionKey.toString();
|
||||||
|
|
||||||
|
const foundGroup = this.sorted_options.find(groupOption => {
|
||||||
|
if (!Array.isArray(groupOption.value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupOption.value.some(option => option.key == normalizedKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!foundGroup) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundGroup.key ? foundGroup.key.toString() : '';
|
||||||
|
},
|
||||||
|
|
||||||
sortBy(option) {
|
sortBy(option) {
|
||||||
return (firstEl, secondEl) => {
|
return (firstEl, secondEl) => {
|
||||||
let first_element = firstEl[option].toUpperCase(); // ignore upper and lowercase
|
let first_element = firstEl[option].toUpperCase(); // ignore upper and lowercase
|
||||||
|
|
@ -910,6 +1048,8 @@ export default {
|
||||||
visibleChange(event) {
|
visibleChange(event) {
|
||||||
this.$emit('visible-change', event);
|
this.$emit('visible-change', event);
|
||||||
|
|
||||||
|
this.isDropdownVisible = event;
|
||||||
|
|
||||||
this.dynamicPlaceholder = this.placeholder;
|
this.dynamicPlaceholder = this.placeholder;
|
||||||
|
|
||||||
if (event && this.searchText) {
|
if (event && this.searchText) {
|
||||||
|
|
@ -1492,11 +1632,25 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.aka-select-prefix {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.with-color-prefix .el-input__inner {
|
||||||
|
padding-left: 2.25rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.with-color-prefix.with-icon-prefix .el-input__inner {
|
||||||
|
padding-left: 2.8rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
.el-select-dropdown__item.el-select__footer.bg-purple.sticky.bottom-0 {
|
.el-select-dropdown__item.el-select__footer.bg-purple.sticky.bottom-0 {
|
||||||
background-color: #fff !important;
|
background-color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-select-dropdown__item.el-select__footer.bg-purple.sticky.bottom-0:hover {
|
.el-select-dropdown__item.el-select__footer.bg-purple.sticky.bottom-0:hover {
|
||||||
background-color: 55588b !important;
|
background-color: #55588b !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
@if ((! $attributes->has('withoutRemote') && ! $attributes->has('without-remote')) && (! $attributes->has('withoutAddNew') && ! $attributes->has('without-add-new')))
|
@if (
|
||||||
|
(! $attributes->has('withoutRemote') && ! $attributes->has('without-remote'))
|
||||||
|
&& (! $attributes->has('withoutAddNew') && ! $attributes->has('without-add-new'))
|
||||||
|
)
|
||||||
<x-form.group.select
|
<x-form.group.select
|
||||||
remote
|
remote
|
||||||
remote_action="{{ $remoteAction }}"
|
remote_action="{{ $remoteAction }}"
|
||||||
|
|
@ -11,10 +14,7 @@
|
||||||
:options="$categories"
|
:options="$categories"
|
||||||
:selected="$selected"
|
:selected="$selected"
|
||||||
sort-options="false"
|
sort-options="false"
|
||||||
:option_field="[
|
:option_field="$option_field"
|
||||||
'key' => 'id',
|
|
||||||
'value' => 'title'
|
|
||||||
]"
|
|
||||||
|
|
||||||
:multiple="$multiple"
|
:multiple="$multiple"
|
||||||
:group="$group"
|
:group="$group"
|
||||||
|
|
@ -28,11 +28,19 @@
|
||||||
<template #option="{option}">
|
<template #option="{option}">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span class="w-5 h-4 rounded-full" :style="{backgroundColor: option.option.color_hex_code}"></span>
|
<span class="w-5 h-4 rounded-full" :style="{backgroundColor: option.option.color_hex_code}"></span>
|
||||||
|
|
||||||
|
@if ($option_field['value'] == 'title')
|
||||||
|
<span>@{{ option.option.title }}</span>
|
||||||
|
@else
|
||||||
<span>@{{ option.option.name }}</span>
|
<span>@{{ option.option.name }}</span>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</x-form.group.select>
|
</x-form.group.select>
|
||||||
@elseif (($attributes->has('withoutRemote') || $attributes->has('without-remote')) && (! $attributes->has('withoutAddNew') && ! $attributes->has('without-add-new')))
|
@elseif (
|
||||||
|
($attributes->has('withoutRemote') || $attributes->has('without-remote'))
|
||||||
|
&& (! $attributes->has('withoutAddNew') && ! $attributes->has('without-add-new'))
|
||||||
|
)
|
||||||
<x-form.group.select
|
<x-form.group.select
|
||||||
add-new
|
add-new
|
||||||
path="{{ $path }}"
|
path="{{ $path }}"
|
||||||
|
|
@ -42,10 +50,7 @@
|
||||||
:options="$categories"
|
:options="$categories"
|
||||||
:selected="$selected"
|
:selected="$selected"
|
||||||
sort-options="false"
|
sort-options="false"
|
||||||
:option_field="[
|
:option_field="$option_field"
|
||||||
'key' => 'id',
|
|
||||||
'value' => 'title'
|
|
||||||
]"
|
|
||||||
|
|
||||||
:multiple="$multiple"
|
:multiple="$multiple"
|
||||||
:group="$group"
|
:group="$group"
|
||||||
|
|
@ -59,11 +64,19 @@
|
||||||
<template #option="{option}">
|
<template #option="{option}">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span class="w-5 h-4 rounded-full" :style="{backgroundColor: option.option.color_hex_code}"></span>
|
<span class="w-5 h-4 rounded-full" :style="{backgroundColor: option.option.color_hex_code}"></span>
|
||||||
|
|
||||||
|
@if ($option_field['value'] == 'title')
|
||||||
|
<span>@{{ option.option.title }}</span>
|
||||||
|
@else
|
||||||
<span>@{{ option.option.name }}</span>
|
<span>@{{ option.option.name }}</span>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</x-form.group.select>
|
</x-form.group.select>
|
||||||
@elseif ((! $attributes->has('withoutRemote') && ! $attributes->has('without-remote')) && ($attributes->has('withoutAddNew') || $attributes->has('without-add-new')))
|
@elseif (
|
||||||
|
(! $attributes->has('withoutRemote') && ! $attributes->has('without-remote'))
|
||||||
|
&& ($attributes->has('withoutAddNew') || $attributes->has('without-add-new'))
|
||||||
|
)
|
||||||
<x-form.group.select
|
<x-form.group.select
|
||||||
remote
|
remote
|
||||||
remote_action="{{ $remoteAction }}"
|
remote_action="{{ $remoteAction }}"
|
||||||
|
|
@ -73,10 +86,7 @@
|
||||||
:options="$categories"
|
:options="$categories"
|
||||||
:selected="$selected"
|
:selected="$selected"
|
||||||
sort-options="false"
|
sort-options="false"
|
||||||
:option_field="[
|
:option_field="$option_field"
|
||||||
'key' => 'id',
|
|
||||||
'value' => 'title'
|
|
||||||
]"
|
|
||||||
|
|
||||||
:multiple="$multiple"
|
:multiple="$multiple"
|
||||||
:group="$group"
|
:group="$group"
|
||||||
|
|
@ -90,7 +100,12 @@
|
||||||
<template #option="{option}">
|
<template #option="{option}">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span class="w-5 h-4 rounded-full" :style="{backgroundColor: option.option.color_hex_code}"></span>
|
<span class="w-5 h-4 rounded-full" :style="{backgroundColor: option.option.color_hex_code}"></span>
|
||||||
|
|
||||||
|
@if ($option_field['value'] == 'title')
|
||||||
|
<span>@{{ option.option.title }}</span>
|
||||||
|
@else
|
||||||
<span>@{{ option.option.name }}</span>
|
<span>@{{ option.option.name }}</span>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</x-form.group.select>
|
</x-form.group.select>
|
||||||
|
|
@ -101,10 +116,7 @@
|
||||||
:options="$categories"
|
:options="$categories"
|
||||||
:selected="$selected"
|
:selected="$selected"
|
||||||
sort-options="false"
|
sort-options="false"
|
||||||
:option_field="[
|
:option_field="$option_field"
|
||||||
'key' => 'id',
|
|
||||||
'value' => 'title'
|
|
||||||
]"
|
|
||||||
|
|
||||||
:multiple="$multiple"
|
:multiple="$multiple"
|
||||||
:group="$group"
|
:group="$group"
|
||||||
|
|
@ -117,8 +129,13 @@
|
||||||
>
|
>
|
||||||
<template #option="{option}">
|
<template #option="{option}">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span class="w-5 h-4 rounded-full":style="{backgroundColor: option.option.color_hex_code}"></span>
|
<span class="w-5 h-4 rounded-full" :style="{backgroundColor: option.option.color_hex_code}"></span>
|
||||||
|
|
||||||
|
@if ($option_field['value'] == 'title')
|
||||||
|
<span>@{{ option.option.title }}</span>
|
||||||
|
@else
|
||||||
<span>@{{ option.option.name }}</span>
|
<span>@{{ option.option.name }}</span>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</x-form.group.select>
|
</x-form.group.select>
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,9 @@
|
||||||
</x-slot>
|
</x-slot>
|
||||||
|
|
||||||
<x-slot name="body">
|
<x-slot name="body">
|
||||||
<x-form.group.select remote name="income_category" label="{{ trans('settings.default.income_category') }}" :options="$sales_categories" :clearable="'false'" :selected="setting('default.income_category')" remote_action="{{ route('categories.index'). '?search=type:income enabled:1' }}" sort-options="false" />
|
<x-form.group.select remote name="income_category" label="{{ trans('settings.default.income_category') }}" :options="$sales_categories" :clearable="'false'" :selected="setting('default.income_category')" remote_action="{{ route('categories.index'). '?search=type:' . $income_category_types . ' enabled:1' }}" sort-options="false" />
|
||||||
|
|
||||||
<x-form.group.select remote name="expense_category" label="{{ trans('settings.default.expense_category') }}" :options="$purchases_categories" :clearable="'false'" :selected="setting('default.expense_category')" remote_action="{{ route('categories.index'). '?search=type:expense enabled:1' }}" sort-options="false" />
|
<x-form.group.select remote name="expense_category" label="{{ trans('settings.default.expense_category') }}" :options="$purchases_categories" :clearable="'false'" :selected="setting('default.expense_category')" remote_action="{{ route('categories.index'). '?search=type:' . $expense_category_types . ' enabled:1' }}" sort-options="false" />
|
||||||
</x-slot>
|
</x-slot>
|
||||||
</x-form.section>
|
</x-form.section>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue