diff --git a/app/Enums/StatusTypeEnum.php b/app/Enums/StatusTypeEnum.php new file mode 100644 index 0000000..eb1801c --- /dev/null +++ b/app/Enums/StatusTypeEnum.php @@ -0,0 +1,16 @@ +margin(1) ->size(512) - ->generate("http://localhost:8080/{$asset->id}"), + ->generate(route('asset-details.scans', $asset->id)), ); if ($request->hasFile('attachments')) { diff --git a/app/Http/Controllers/AssetDetailController.php b/app/Http/Controllers/AssetDetailController.php new file mode 100644 index 0000000..d4d9018 --- /dev/null +++ b/app/Http/Controllers/AssetDetailController.php @@ -0,0 +1,17 @@ +orWhere('date', 'LIKE', "%{$search}%") ->orWhere('amount', 'LIKE', "%{$search}%") ->orWhereHas('asset', function (Builder $query) use ($search) { - $query->where('active', true) - ->orWhere('name', 'LIKE', "%{$search}%"); + $query->where('name', 'LIKE', "%{$search}%"); }); }) ->latest() diff --git a/app/Http/Controllers/AssetHistoryController.php b/app/Http/Controllers/AssetHistoryController.php index eb2069f..2b970d9 100644 --- a/app/Http/Controllers/AssetHistoryController.php +++ b/app/Http/Controllers/AssetHistoryController.php @@ -45,8 +45,7 @@ public function index(Request $request): View ->orWhere('condition_percentage', 'LIKE', "%{$search}%") ->orWhere('completeness_percentage', 'LIKE', "%{$search}%") ->orWhereHas('asset', function (Builder $query) use ($search) { - $query->where('active', true) - ->orWhere('name', 'LIKE', "%{$search}%"); + $query->where('name', 'LIKE', "%{$search}%"); }) ->orWhereHas('responsiblePerson', function (Builder $query) use ($search) { $query->where('name', 'LIKE', "%{$search}%"); diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index 2f831f2..757253d 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -31,7 +31,7 @@ public function index(Request $request): View $page = $request->query('page'); $search = $request->query('search'); - $categories = Category::when($search, function (Builder $query, ?string $search) { + $categories = Category::withoutNoneName()->when($search, function (Builder $query, ?string $search) { $query->where('name', 'LIKE', "%{$search}%") ->orWhere('description', 'LIKE', "%{$search}%"); }) diff --git a/app/Http/Controllers/ExportController.php b/app/Http/Controllers/ExportController.php new file mode 100644 index 0000000..6c56c38 --- /dev/null +++ b/app/Http/Controllers/ExportController.php @@ -0,0 +1,251 @@ +middleware('role:'.RoleEnum::Administrator->value.'|'.RoleEnum::Custom->value); + $this->middleware('permission:'.PermissionEnum::DownloadAssets->value); + } + + /** + * Export data from database to pdf. + */ + public function pdf(Request $request, StatusTypeEnum $status): PdfBuilder + { + $assets = Asset::active($status->value === StatusTypeEnum::Active->value) + ->with(['category', 'brand', 'latestHistory', 'assetArchive']) + ->get(); + + $filename = $status->value === StatusTypeEnum::Active->value + ? time().'_Asset Active.pdf' + : time().'_Asset Inactive.pdf'; + + return pdf()->view('asset-exports.pdf.main', compact('assets', 'status')) + ->headerView('asset-exports.pdf.header', compact('status')) + ->footerView('asset-exports.pdf.footer') + ->orientation(Orientation::Landscape) + ->format(Format::Tabloid) + ->margins(128, 16, 56, 16, Unit::Pixel) + ->name($filename) + ->download(); + } + + /** + * Export data from database to xlsx. + */ + public function xlsx(Request $request, StatusTypeEnum $status): BinaryFileResponse + { + $assets = Asset::active($status->value === StatusTypeEnum::Active->value) + ->with(['category', 'brand', 'latestHistory', 'assetArchive']) + ->get(); + + $template = $status->value === StatusTypeEnum::Active->value + ? 'excel-active.xlsx' + : 'excel-inactive.xlsx'; + + $filename = $status->value === StatusTypeEnum::Active->value + ? time().'_Asset Active.xlsx' + : time().'_Asset Inactive.xlsx'; + + PhpExcelTemplator::outputToFile( + resource_path("templates/$template"), + storage_path("app/public/$filename"), + [ + '{date}' => new ExcelParam( + CellSetterStringValue::class, + now()->toDateString(), + ), + '[no]' => new ExcelParam( + CellSetterArrayValue::class, + range(1, $assets->count()), + ), + '[asset_code]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('code')->toArray(), + ), + '[asset_name]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('name')->toArray(), + ), + '[asset_category]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->category?->name)->toArray(), + ), + '[asset_brand]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->brand?->name)->toArray(), + ), + '[asset_type]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('type')->toArray(), + ), + '[asset_manufacturer]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('manufacturer')->toArray(), + ), + '[asset_serial_number]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('serial_number')->toArray(), + ), + '[asset_production_year]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('production_year')->toArray(), + ), + '[asset_description]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('description')->toArray(), + ), + '[asset_purchase_date]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('purchase_date')->toArray(), + ), + '[asset_distributor]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->distributor?->name)->toArray(), + ), + '[asset_invoice_number]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('invoice_number')->toArray(), + ), + '[asset_qty]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('qty')->toArray(), + ), + '[asset_unit_price]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('unit_price')->toArray(), + ), + '[asset_total_price]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('total_price')->toArray(), + ), + '[archive_inactive_date]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->assetArchive?->inactive_date)->toArray(), + ), + '[archive_reason]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->assetArchive?->reason->label())->toArray(), + ), + '[archive_notes]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->assetArchive?->notes)->toArray(), + ), + '[history_date_from]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->latestHistory?->date_from)->toArray(), + ), + '[history_responsible_person]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->latestHistory?->responsiblePerson?->name)->toArray(), + ), + '[history_location]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->latestHistory?->location?->name)->toArray(), + ), + '[history_qty]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->latestHistory?->qty)->toArray(), + ), + '[history_condition]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->latestHistory?->condition_percentage)->toArray(), + ), + '[history_completeness]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->latestHistory?->completeness_percentage)->toArray(), + ), + '[history_notes]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->map(fn (Asset $asset) => $asset->latestHistory?->notes)->toArray(), + ), + '[asset_notes]' => new ExcelParam( + CellSetterArrayValue::class, + $assets->pluck('notes')->toArray(), + ), + ], + ); + + return response()->download(storage_path("app/public/$filename")) + ->deleteFileAfterSend(); + } + + /** + * Export data from database to docx. + */ + public function docx(Request $request, StatusTypeEnum $status): BinaryFileResponse + { + $assets = Asset::active($status->value === StatusTypeEnum::Active->value) + ->with(['category', 'brand', 'latestHistory', 'assetArchive']) + ->get(); + + $template = $status->value === StatusTypeEnum::Active->value + ? 'word-active.docx' + : 'word-inactive.docx'; + + $filename = $status->value === StatusTypeEnum::Active->value + ? time().'_Asset Active.docx' + : time().'_Asset Inactive.docx'; + + $phpWord = new TemplateProcessor(resource_path("templates/$template")); + $phpWord->setValue('date', now()->toDateString()); + $phpWord->cloneRowAndSetValues('asset_code', $assets->map(fn (Asset $asset, int $key) => [ + 'no' => $key + 1, + 'asset_code' => $asset->code, + 'asset_name' => $asset->name, + 'asset_category' => $asset->category?->name, + 'asset_brand' => $asset->brand?->name, + 'asset_type' => $asset->type, + 'asset_manufacturer' => $asset->manufacturer, + 'asset_serial_number' => $asset->serial_number, + 'asset_production_year' => $asset->production_year, + 'asset_description' => $asset->description, + 'asset_purchase_date' => $asset->purchase_date, + 'asset_distributor' => $asset->distributor?->name, + 'asset_invoice_number' => $asset->invoice_number, + 'asset_qty' => $asset->qty, + 'asset_unit_price' => $asset->unit_price, + 'asset_total_price' => $asset->total_price, + 'archive_inactive_date' => $asset->assetArchive?->inactive_date, + 'archive_reason' => $asset->assetArchive?->reason->label(), + 'archive_notes' => $asset->assetArchive?->notes, + 'history_date_from' => $asset->latestHistory?->date_from, + 'history_responsible_person' => $asset->latestHistory?->responsiblePerson?->name, + 'history_location' => $asset->latestHistory?->location?->name, + 'history_qty' => $asset->latestHistory?->qty, + 'history_condition' => $asset->latestHistory?->condition_percentage, + 'history_completeness' => $asset->latestHistory?->completeness_percentage, + 'history_notes' => $asset->latestHistory?->notes, + 'asset_notes' => $asset->notes, + ])->toArray()); + + $phpWord->saveAs(storage_path("app/public/$filename")); + + return response()->download(storage_path("app/public/$filename")) + ->deleteFileAfterSend(); + } +} diff --git a/app/Http/Controllers/PrintController.php b/app/Http/Controllers/PrintController.php index 78c3817..1c01a6f 100644 --- a/app/Http/Controllers/PrintController.php +++ b/app/Http/Controllers/PrintController.php @@ -12,6 +12,7 @@ use Spatie\LaravelPdf\Enums\Orientation; use Spatie\LaravelPdf\Enums\Unit; use Spatie\LaravelPdf\PdfBuilder; + use function Spatie\LaravelPdf\Support\pdf; class PrintController extends Controller @@ -21,8 +22,8 @@ class PrintController extends Controller */ public function __construct() { - $this->middleware('role:' . RoleEnum::Administrator->value . '|' . RoleEnum::Custom->value); - $this->middleware('permission:' . PermissionEnum::CreatePrints->value); + $this->middleware('role:'.RoleEnum::Administrator->value.'|'.RoleEnum::Custom->value); + $this->middleware('permission:'.PermissionEnum::CreatePrints->value); } /** @@ -69,6 +70,6 @@ public function store(StorePrintRequest $request): PdfBuilder ->orientation(Orientation::Portrait) ->format(Format::A4) ->margins(56, 16, 56, 16, Unit::Pixel) - ->name(time() . "- {$asset->name}.pdf"); + ->name(time()."- {$asset->name}.pdf"); } } diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php new file mode 100644 index 0000000..627b014 --- /dev/null +++ b/app/Http/Controllers/ProfileController.php @@ -0,0 +1,43 @@ +name = $request->input('name'); + $user->email = $request->input('email'); + $user->description = $request->input('description'); + + if ($request->filled('password')) { + $user->password = Hash::make($request->input('password')); + } + + $user->save(); + + return redirect()->route('profile.edit') + ->with('message', 'The profile has been updated.'); + + } +} diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 5035ba8..28794dc 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -32,7 +32,7 @@ public function index(Request $request): View $page = $request->query('page'); $search = $request->query('search'); - $users = User::withoutAdminRole()->when($search, function (Builder $query, ?string $search) { + $users = User::withoutAdministratorRole()->when($search, function (Builder $query, ?string $search) { $query->where('name', 'LIKE', "%{$search}%") ->orWhere('email', 'LIKE', "%{$search}%") ->orWhere('description', 'LIKE', "%{$search}%"); diff --git a/app/Http/Requests/StoreAssetRequest.php b/app/Http/Requests/StoreAssetRequest.php index c529e7e..3728b4a 100644 --- a/app/Http/Requests/StoreAssetRequest.php +++ b/app/Http/Requests/StoreAssetRequest.php @@ -45,7 +45,7 @@ public function rules(): array 'nullable', 'image', 'max:1024', - 'mimes:jpg,jpeg,png', + 'mimes:jpeg,png', ], 'brand' => [ 'required', @@ -121,7 +121,6 @@ public function rules(): array 'attachments.*' => [ 'nullable', 'file', - 'max:1024', ], 'notes' => [ 'nullable', diff --git a/app/Http/Requests/UpdateAssetRequest.php b/app/Http/Requests/UpdateAssetRequest.php index 7984d18..e621079 100644 --- a/app/Http/Requests/UpdateAssetRequest.php +++ b/app/Http/Requests/UpdateAssetRequest.php @@ -46,7 +46,7 @@ public function rules(): array 'nullable', 'image', 'max:1024', - 'mimes:jpg,jpeg,png', + 'mimes:jpeg,png', ], 'brand' => [ 'required', @@ -122,7 +122,6 @@ public function rules(): array 'attachments.*' => [ 'nullable', 'file', - 'max:1024', ], 'notes' => [ 'nullable', diff --git a/app/Http/Requests/UpdateProfileRequest.php b/app/Http/Requests/UpdateProfileRequest.php new file mode 100644 index 0000000..8802d10 --- /dev/null +++ b/app/Http/Requests/UpdateProfileRequest.php @@ -0,0 +1,50 @@ +|string> + */ + public function rules(): array + { + return [ + 'name' => [ + 'required', + 'string', + 'min:3', + 'max:100', + ], + 'email' => [ + 'required', + 'email', + Rule::unique('users', 'email')->ignore($this->user()), + ], + 'password' => [ + 'nullable', + 'string', + 'confirmed', + Password::min(8) + ->letters() + ->mixedCase() + ->numbers() + ->symbols(), + ], + ]; + } +} diff --git a/app/Models/Category.php b/app/Models/Category.php index 4a2c367..4a2c8eb 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -2,6 +2,7 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -56,6 +57,14 @@ class Category extends Model 'description', ]; + /** + * Scope a query to only include without none name. + */ + public function scopeWithoutNoneName(Builder $query): void + { + $query->whereNot('name', 'None'); + } + /** * Get the assets for the category. */ diff --git a/app/Models/User.php b/app/Models/User.php index 5f5d61a..3e56626 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -84,9 +84,9 @@ class User extends Authenticatable implements LaratrustUser ]; /** - * Scope a query to only include active asset. + * Scope a query to only include without administrator role. */ - public function scopeWithoutAdminRole(Builder $query): void + public function scopeWithoutAdministratorRole(Builder $query): void { $query->whereDoesntHave('roles', function ($query) { $query->where('name', RoleEnum::Administrator->value); diff --git a/composer.json b/composer.json index 6560995..3bc702e 100644 --- a/composer.json +++ b/composer.json @@ -6,10 +6,13 @@ "license": "MIT", "require": { "php": "^8.1", + "alhimik1986/php-excel-templator": "^1.0", "guzzlehttp/guzzle": "^7.2", "laravel/framework": "^10.0", "laravel/sanctum": "^3.2", "laravel/tinker": "^2.8", + "phpoffice/phpspreadsheet": "1.29.2", + "phpoffice/phpword": "^1.3", "santigarcor/laratrust": "^8.3", "simplesoftwareio/simple-qrcode": "~1", "spatie/laravel-pdf": "^1.5" diff --git a/package.json b/package.json index 899cb91..ae66a81 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "vite": "^4.0.0" }, "dependencies": { + "active-menu-link": "^1.1.8", "autosize": "^6.0.1", "puppeteer": "^23.5.0", "tw-elements": "^1.1.0" diff --git a/resources/js/app.js b/resources/js/app.js index 0328b36..1dff400 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -261,25 +261,25 @@ inputList.map((inputItem) => { inputFormWhite: false, }, { notch: - "group flex w-full max-w-full h-full text-left select-none pointer-events-none absolute transition-all top-0 after:content[''] after:block after:w-full after:absolute after:bottom-0 left-0 after:border-b-2 after:transition-transform after:duration-300 after:scale-x-0 after:border-primary peer-focus:after:scale-x-100 peer-focus:after:border-primary peer-data-[te-input-focused]:after:scale-x-100 peer-data-[te-input-focused]:after:border-primary group-data-[te-validation-state='invalid']:after:!border-error peer-[.is-invalid]:after:!border-error peer-[.is-invalid]:peer-focus:after:!border-error peer-[.is-invalid]:peer-data-[te-input-focused]:after:!border-error", + "group/notch flex absolute left-0 top-0 w-full max-w-full h-full text-left pointer-events-none", notchLeading: - "pointer-events-none border-b border-solid box-border bg-transparent transition-none duration-0 left-0 top-0 h-full w-0 border-r-0 rounded-l-none group-data-[te-input-focused]:border-r-0 group-data-[te-input-state-active]:border-r-0 peer-disabled:group-[]:border-dotted", + "pointer-events-none border border-solid box-border bg-transparent transition-none duration-0 ease-linear motion-reduce:transition-none left-0 top-0 h-full w-2 border-r-0 rounded-l-[0.25rem] group-data-[te-input-focused]/notch:border-r-0 group-data-[te-input-state-active]/notch:border-r-0 peer-disabled:group-[]/notch:!opacity-60", notchLeadingNormal: - "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]:shadow-none group-data-[te-input-focused]:border-black/[0.24] dark:group-data-[te-input-focused]:border-white/[0.24] group-has-[.is-invalid]:!border-error group-has-[.is-invalid]:dark:!border-error", + "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]/notch:shadow-[-1px_0_0_theme(colors.primary),_0_1px_0_0_theme(colors.primary),_0_-1px_0_0_theme(colors.primary)] group-data-[te-input-focused]/notch:border-primary peer-focus:group-[]/notch:shadow-[-1px_0_0_theme(colors.primary),_0_1px_0_0_theme(colors.primary),_0_-1px_0_0_theme(colors.primary)] peer-focus:group-[]/notch:border-primary group-has-[.is-invalid]:group-data-[te-input-focused]/notch:shadow-[-1px_0_0_theme(colors.error),_0_1px_0_0_theme(colors.error),_0_-1px_0_0_theme(colors.error)] group-has-[.is-invalid]:peer-focus:group-[]/notch:shadow-[-1px_0_0_theme(colors.error),_0_1px_0_0_theme(colors.error),_0_-1px_0_0_theme(colors.error)] group-has-[.is-invalid]:!border-error", notchLeadingWhite: - "border-neutral-200 group-data-[te-input-focused]:shadow-[-1px_0_0_#ffffff,_0_1px_0_0_#ffffff,_0_-1px_0_0_#ffffff] group-data-[te-input-focused]:border-white", + "border-neutral-200 group-data-[te-input-focused]/notch:shadow-[-1px_0_0_#ffffff,_0_1px_0_0_#ffffff,_0_-1px_0_0_#ffffff] group-data-[te-input-focused]/notch:border-white", notchMiddle: - "pointer-events-none border-b border-solid box-border bg-transparent transition-none duration-0 grow-0 shrink-0 basis-auto w-auto max-w-[calc(100%-1rem)] h-full border-r-0 border-l-0 group-data-[te-input-focused]:border-x-0 group-data-[te-input-state-active]:border-x-0 group-data-[te-input-focused]:border-t-0 group-data-[te-input-state-active]:border-t-0 group-data-[te-input-focused]:border-solid group-data-[te-input-state-active]:border-solid group-data-[te-input-focused]:border-t-transparent group-data-[te-input-state-active]:border-t-transparent peer-disabled:group-[]:border-dotted", + "pointer-events-none border border-solid box-border bg-transparent transition-none duration-0 ease-linear motion-reduce:transition-none grow-0 shrink-0 basis-auto w-auto max-w-[calc(100%-1rem)] h-full border-r-0 border-l-0 group-data-[te-input-focused]/notch:border-x-0 group-data-[te-input-state-active]/notch:border-x-0 group-data-[te-input-focused]/notch:border-t group-data-[te-input-state-active]/notch:border-t group-data-[te-input-focused]/notch:border-solid group-data-[te-input-state-active]/notch:border-solid group-data-[te-input-focused]/notch:!border-t-transparent group-data-[te-input-state-active]/notch:!border-t-transparent peer-focus:group-[]/notch:!border-t-transparent peer-active:group-[]/notch:!border-t-transparent peer-disabled:peer-[&:not([data-te-input-state-active])]:group-[]/notch:!border-t-black/[0.24] peer-disabled:group-[]/notch:!opacity-60", notchMiddleNormal: - "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]:shadow-none group-data-[te-input-focused]:border-black/[0.24] dark:group-data-[te-input-focused]:border-white/[0.24] group-has-[.is-invalid]:!border-error group-has-[.is-invalid]:dark:!border-error", + "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]/notch:shadow-[0_1px_0_0_theme(colors.primary)] group-data-[te-input-focused]/notch:border-primary peer-focus:group-[]/notch:shadow-[0_1px_0_0_theme(colors.primary)] peer-focus:group-[]/notch:border-primary group-has-[.is-invalid]:group-data-[te-input-focused]/notch:shadow-[0_1px_0_0_theme(colors.error)] group-has-[.is-invalid]:peer-focus:group-[]/notch:shadow-[0_1px_0_0_theme(colors.error)] group-has-[.is-invalid]:!border-error", notchMiddleWhite: - "border-neutral-200 group-data-[te-input-focused]:shadow-[0_1px_0_0_#ffffff] group-data-[te-input-focused]:border-white", + "border-neutral-200 group-data-[te-input-focused]/notch:shadow-[0_1px_0_0_#ffffff] group-data-[te-input-focused]/notch:border-white", notchTrailing: - "pointer-events-none border-b border-solid box-border bg-transparent transition-none duration-0 grow h-full border-l-0 rounded-r-none group-data-[te-input-focused]:border-l-0 group-data-[te-input-state-active]:border-l-0 peer-disabled:group-[]:border-dotted", + "pointer-events-none border border-solid box-border bg-transparent transition-none duration-0 ease-linear motion-reduce:transition-none grow h-full border-l-0 rounded-r-[0.25rem] group-data-[te-input-focused]/notch:border-l-0 group-data-[te-input-state-active]/notch:border-l-0 peer-disabled:group-[]/notch:!opacity-60", notchTrailingNormal: - "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]:shadow-none group-data-[te-input-focused]:border-black/[0.24] dark:group-data-[te-input-focused]:border-white/[0.24] group-has-[.is-invalid]:!border-error group-has-[.is-invalid]:dark:!border-error", + "border-black/[0.24] dark:border-neutral-600 group-data-[te-input-focused]/notch:shadow-[1px_0_0_theme(colors.primary),_0_-1px_0_0_theme(colors.primary),_0_1px_0_0_theme(colors.primary)] group-data-[te-input-focused]/notch:border-primary peer-focus:group-[]/notch:shadow-[1px_0_0_theme(colors.primary),_0_-1px_0_0_theme(colors.primary),_0_1px_0_0_theme(colors.primary)] peer-focus:group-[]/notch:border-primary group-has-[.is-invalid]:group-data-[te-input-focused]/notch:shadow-[1px_0_0_theme(colors.error),_0_-1px_0_0_theme(colors.error),_0_1px_0_0_theme(colors.error)] group-has-[.is-invalid]:peer-focus:group-[]/notch:shadow-[1px_0_0_theme(colors.error),_0_-1px_0_0_theme(colors.error),_0_1px_0_0_theme(colors.error)] group-has-[.is-invalid]:!border-error", notchTrailingWhite: - "border-neutral-200 group-data-[te-input-focused]:shadow-[1px_0_0_#ffffff,_0_-1px_0_0_#ffffff,_0_1px_0_0_#ffffff] group-data-[te-input-focused]:border-white", + "border-neutral-200 group-data-[te-input-focused]/notch:shadow-[1px_0_0_#ffffff,_0_-1px_0_0_#ffffff,_0_1px_0_0_#ffffff] group-data-[te-input-focused]/notch:border-white", counter: "text-right leading-[1.6]", }); @@ -400,7 +400,7 @@ selectList.map((selectItem) => { optionsWrapperScrollbar: "[&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar]:h-1 [&::-webkit-scrollbar-button]:block [&::-webkit-scrollbar-button]:h-0 [&::-webkit-scrollbar-button]:bg-transparent [&::-webkit-scrollbar-track-piece]:bg-transparent [&::-webkit-scrollbar-track-piece]:rounded-none [&::-webkit-scrollbar-track-piece]: [&::-webkit-scrollbar-track-piece]:rounded-l [&::-webkit-scrollbar-thumb]:h-[50px] [&::-webkit-scrollbar-thumb]:bg-[#999] [&::-webkit-scrollbar-thumb]:rounded", selectArrow: - "block w-9 h-9 p-1.5 m-0 text-black/[0.60] rounded-full align-middle cursor-pointer outline-none transition duration-150 ease-in-out absolute right-0 !top-1/2 -translate-y-1/2 z-0 dark:text-white/[0.60] peer-disabled:opacity-70 peer-disabled:cursor-not-allowed peer-disabled:hover:!bg-transparent peer-disabled:active:!bg-transparent peer-disabled:focus:!bg-transparent", + "block w-9 h-9 p-1.5 m-0 text-black/[0.60] rounded-full align-middle cursor-pointer outline-none transition duration-150 ease-in-out absolute right-1 !top-1/2 -translate-y-1/2 z-0 dark:text-white/[0.60] peer-disabled:opacity-70 peer-disabled:cursor-not-allowed peer-disabled:hover:!bg-transparent peer-disabled:active:!bg-transparent peer-disabled:focus:!bg-transparent", selectArrowWhite: "text-gray-50 peer-focus:!text-white peer-data-[te-input-focused]:!text-white", selectArrowDefault: @@ -426,17 +426,17 @@ selectList.map((selectItem) => { selectFilterInput: "relative m-0 block w-full min-w-0 flex-auto rounded border border-solid border-gray-300 bg-transparent bg-clip-padding px-3 py-1.5 text-base font-normal text-gray-700 transition duration-300 ease-in-out motion-reduce:transition-none focus:border-primary focus:text-gray-700 focus:shadow-te-primary focus:outline-none dark:text-gray-200 dark:placeholder:text-gray-200", selectInput: - "peer block min-h-[48px] w-full border-0 bg-transparent pt-3 pb-2 subtitle-1 text-black/[0.87] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white/[0.87] dark:placeholder:text-white/[0.87] [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0 disabled:opacity-60 disabled:cursor-not-allowed group-has-[.is-invalid]:!caret-error", + "peer caret-primary block min-h-[48px] w-full rounded border-0 bg-transparent pl-3 pr-11 py-3 subtitle-1 text-black/[0.87] outline-none transition-none duration-0 ease-linear focus:placeholder:opacity-100 file:hidden file:w-0 file:opacity-0 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white/[0.87] dark:placeholder:text-white/[0.87] [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0 [&[type='file']]:opacity-0 group-data-[te-validation-state='invalid']:!caret-error disabled:!opacity-60 disabled:cursor-not-allowed group-has-[[data-te-input-state-active]]:opacity-100 group-has-[.is-invalid]:!caret-error", selectInputWhite: "!text-gray-50", selectInputSizeDefault: - "p-0 m-0 leading-[1.6]", + "p-0 m-0 leading-normal", selectInputSizeLg: - "py-[0.32rem] px-3 leading-[2.15]", + "py-[0.32rem] px-3 leading-normal", selectInputSizeSm: - "py-[0.33rem] px-3 text-xs leading-[1.5]", + "py-[0.33rem] px-3 text-xs leading-normal", selectLabel: - "pointer-events-none absolute top-0 left-0 mb-0 max-w-[90%] origin-[0_0] truncate text-black/[0.60] transition-all duration-200 ease-out peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:scale-[0.8] peer-data-[te-input-focused]:text-primary motion-reduce:transition-none dark:text-white/[0.60] dark:peer-focus:text-primary data-[te-input-state-active]:scale-[0.8] group-data-[te-validation-state='invalid']:!text-error group-data-[te-validation-state='invalid']:peer-focus:!text-error peer-disabled:opacity-60 peer-disabled:cursor-not-allowed group-has-[.is-invalid]:!text-error group-has-[.is-invalid]:peer-focus:!text-error group-has-[.is-invalid]:peer-data-[te-input-focused]:!text-error group-has-[.is-invalid]:dark:!text-error group-has-[.is-invalid]:dark:peer-focus:!text-error group-has-[.is-invalid]:dark:peer-data-[te-input-focused]:!text-error", + "pointer-events-none absolute top-0 left-3 mb-0 max-w-[90%] origin-[0_0] truncate text-black/[0.60] transition-all duration-200 ease-out peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:scale-[0.8] peer-data-[te-input-focused]:text-primary motion-reduce:transition-none dark:text-white/[0.60] dark:peer-focus:text-primary data-[te-input-state-active]:scale-[0.8] group-data-[te-validation-state='invalid']:!text-error group-data-[te-validation-state='invalid']:peer-focus:!text-error peer-disabled:opacity-60 peer-disabled:cursor-not-allowed group-has-[.is-invalid]:!text-error group-has-[.is-invalid]:peer-focus:!text-error group-has-[.is-invalid]:peer-data-[te-input-focused]:!text-error group-has-[.is-invalid]:dark:!text-error group-has-[.is-invalid]:dark:peer-focus:!text-error group-has-[.is-invalid]:dark:peer-data-[te-input-focused]:!text-error", selectLabelWhite: "!text-gray-50", selectLabelSizeDefault: @@ -466,19 +466,27 @@ selectList.map((selectItem) => { /** Code below is input style */ notch: - "group flex w-full max-w-full h-full text-left select-none pointer-events-none absolute transition-all top-0 after:content[''] after:block after:w-full after:absolute after:bottom-0 left-0 after:border-b-2 after:transition-transform after:duration-300 after:scale-x-0 after:border-primary peer-focus:after:scale-x-100 peer-focus:after:border-primary peer-data-[te-input-focused]:after:scale-x-100 peer-data-[te-input-focused]:after:border-primary group-data-[te-validation-state='invalid']:after:!border-error group-has-[.is-invalid]:after:!border-error group-has-[.is-invalid]:peer-focus:after:!border-error group-has-[.is-invalid]:peer-data-[te-input-focused]:after:!border-error", + "group/notch flex absolute left-0 top-0 w-full max-w-full h-full text-left pointer-events-none", notchLeading: - "pointer-events-none border-b border-solid box-border bg-transparent transition-none duration-0 left-0 top-0 h-full w-0 border-r-0 rounded-l-none group-data-[te-input-focused]:border-r-0 group-data-[te-input-state-active]:border-r-0 peer-disabled:group-[]:border-dotted", + "pointer-events-none border border-solid box-border bg-transparent transition-none duration-0 ease-linear motion-reduce:transition-none left-0 top-0 h-full w-2 border-r-0 rounded-l-[0.25rem] group-data-[te-input-focused]/notch:border-r-0 group-data-[te-input-state-active]/notch:border-r-0 peer-disabled:group-[]/notch:!opacity-60", notchLeadingNormal: - "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]:shadow-none group-data-[te-input-focused]:border-black/[0.24] dark:group-data-[te-input-focused]:border-white/[0.24] group-has-[.is-invalid]:!border-error group-has-[.is-invalid]:dark:!border-error", + "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]/notch:shadow-[-1px_0_0_theme(colors.primary),_0_1px_0_0_theme(colors.primary),_0_-1px_0_0_theme(colors.primary)] group-data-[te-input-focused]/notch:border-primary peer-data-[te-input-focused]:group-[]/notch:shadow-[-1px_0_0_theme(colors.primary),_0_1px_0_0_theme(colors.primary),_0_-1px_0_0_theme(colors.primary)] peer-data-[te-input-focused]:group-[]/notch:border-primary group-has-[.is-invalid]:group-data-[te-input-focused]/notch:shadow-[-1px_0_0_theme(colors.error),_0_1px_0_0_theme(colors.error),_0_-1px_0_0_theme(colors.error)] group-has-[.is-invalid]:peer-data-[te-input-focused]:group-[]/notch:shadow-[-1px_0_0_theme(colors.error),_0_1px_0_0_theme(colors.error),_0_-1px_0_0_theme(colors.error)] group-has-[.is-invalid]:!border-error", + notchLeadingWhite: + "border-neutral-200 group-data-[te-input-focused]/notch:shadow-[-1px_0_0_#ffffff,_0_1px_0_0_#ffffff,_0_-1px_0_0_#ffffff] group-data-[te-input-focused]/notch:border-white", notchMiddle: - "pointer-events-none border-b border-solid box-border bg-transparent transition-none duration-0 grow-0 shrink-0 basis-auto w-auto max-w-[calc(100%-1rem)] h-full border-r-0 border-l-0 group-data-[te-input-focused]:border-x-0 group-data-[te-input-state-active]:border-x-0 group-data-[te-input-focused]:border-t-0 group-data-[te-input-state-active]:border-t-0 group-data-[te-input-focused]:border-solid group-data-[te-input-state-active]:border-solid group-data-[te-input-focused]:border-t-transparent group-data-[te-input-state-active]:border-t-transparent peer-disabled:group-[]:border-dotted", + "pointer-events-none border border-solid box-border bg-transparent transition-none duration-0 ease-linear motion-reduce:transition-none grow-0 shrink-0 basis-auto w-auto max-w-[calc(100%-1rem)] h-full border-r-0 border-l-0 group-data-[te-input-focused]/notch:border-x-0 group-data-[te-input-state-active]/notch:border-x-0 group-data-[te-input-focused]/notch:border-t group-data-[te-input-state-active]/notch:border-t group-data-[te-input-focused]/notch:border-solid group-data-[te-input-state-active]/notch:border-solid group-data-[te-input-focused]/notch:!border-t-transparent group-data-[te-input-state-active]/notch:!border-t-transparent peer-data-[te-input-focused]:group-[]/notch:!border-t-transparent peer-active:group-[]/notch:!border-t-transparent peer-disabled:peer-[&:not([data-te-input-state-active])]:group-[]/notch:!border-t-black/[0.24] peer-disabled:group-[]/notch:!opacity-60", notchMiddleNormal: - "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]:shadow-none group-data-[te-input-focused]:border-black/[0.24] dark:group-data-[te-input-focused]:border-white/[0.24] group-has-[.is-invalid]:!border-error group-has-[.is-invalid]:dark:!border-error", + "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]/notch:shadow-[0_1px_0_0_theme(colors.primary)] group-data-[te-input-focused]/notch:border-primary peer-data-[te-input-focused]:group-[]/notch:shadow-[0_1px_0_0_theme(colors.primary)] peer-data-[te-input-focused]:group-[]/notch:border-primary group-has-[.is-invalid]:group-data-[te-input-focused]/notch:shadow-[0_1px_0_0_theme(colors.error)] group-has-[.is-invalid]:peer-data-[te-input-focused]:group-[]/notch:shadow-[0_1px_0_0_theme(colors.error)] group-has-[.is-invalid]:!border-error", + notchMiddleWhite: + "border-neutral-200 group-data-[te-input-focused]/notch:shadow-[0_1px_0_0_#ffffff] group-data-[te-input-focused]/notch:border-white", notchTrailing: - "pointer-events-none border-b border-solid box-border bg-transparent transition-none duration-0 grow h-full border-l-0 rounded-r-none group-data-[te-input-focused]:border-l-0 group-data-[te-input-state-active]:border-l-0 peer-disabled:group-[]:border-dotted", + "pointer-events-none border border-solid box-border bg-transparent transition-none duration-0 ease-linear motion-reduce:transition-none grow h-full border-l-0 rounded-r-[0.25rem] group-data-[te-input-focused]/notch:border-l-0 group-data-[te-input-state-active]/notch:border-l-0 peer-disabled:group-[]/notch:!opacity-60", notchTrailingNormal: - "border-black/[0.24] dark:border-white/[0.24] group-data-[te-input-focused]:shadow-none group-data-[te-input-focused]:border-black/[0.24] dark:group-data-[te-input-focused]:border-white/[0.24] group-has-[.is-invalid]:!border-error group-has-[.is-invalid]:dark:!border-error", + "border-black/[0.24] dark:border-neutral-600 group-data-[te-input-focused]/notch:shadow-[1px_0_0_theme(colors.primary),_0_-1px_0_0_theme(colors.primary),_0_1px_0_0_theme(colors.primary)] group-data-[te-input-focused]/notch:border-primary peer-data-[te-input-focused]:group-[]/notch:shadow-[1px_0_0_theme(colors.primary),_0_-1px_0_0_theme(colors.primary),_0_1px_0_0_theme(colors.primary)] peer-data-[te-input-focused]:group-[]/notch:border-primary group-has-[.is-invalid]:group-data-[te-input-focused]/notch:shadow-[1px_0_0_theme(colors.error),_0_-1px_0_0_theme(colors.error),_0_1px_0_0_theme(colors.error)] group-has-[.is-invalid]:peer-data-[te-input-focused]:group-[]/notch:shadow-[1px_0_0_theme(colors.error),_0_-1px_0_0_theme(colors.error),_0_1px_0_0_theme(colors.error)] group-has-[.is-invalid]:!border-error", + notchTrailingWhite: + "border-neutral-200 group-data-[te-input-focused]/notch:shadow-[1px_0_0_#ffffff,_0_-1px_0_0_#ffffff,_0_1px_0_0_#ffffff] group-data-[te-input-focused]/notch:border-white", + counter: + "text-right leading-[1.6]", }); }); diff --git a/resources/templates/excel-active.xlsx b/resources/templates/excel-active.xlsx new file mode 100644 index 0000000..3983688 Binary files /dev/null and b/resources/templates/excel-active.xlsx differ diff --git a/resources/templates/excel-inactive.xlsx b/resources/templates/excel-inactive.xlsx new file mode 100644 index 0000000..a354eb2 Binary files /dev/null and b/resources/templates/excel-inactive.xlsx differ diff --git a/resources/templates/word-active.docx b/resources/templates/word-active.docx new file mode 100644 index 0000000..a368a59 Binary files /dev/null and b/resources/templates/word-active.docx differ diff --git a/resources/templates/word-inactive.docx b/resources/templates/word-inactive.docx new file mode 100644 index 0000000..ae1776e Binary files /dev/null and b/resources/templates/word-inactive.docx differ diff --git a/resources/views/asset-active/create.blade.php b/resources/views/asset-active/create.blade.php index 1923a9c..75c4e01 100644 --- a/resources/views/asset-active/create.blade.php +++ b/resources/views/asset-active/create.blade.php @@ -39,7 +39,7 @@ {{-- Cards --}}