diff --git a/app/Enums/Claims/ClaimExportFormat.php b/app/Enums/Claims/ClaimExportFormat.php new file mode 100644 index 0000000..fae0a4b --- /dev/null +++ b/app/Enums/Claims/ClaimExportFormat.php @@ -0,0 +1,39 @@ +name => 'CSV', + self::pdf->name => 'PDF', + ]; + + public function class() + { + return match ($this) { + self::csv => 'success', + self::pdf => 'danger', + default => 'primary', + }; + } + + public function picto() + { + return match ($this) { + self::csv => 'fa-solid fa-file-csv', + self::pdf => 'fa-solid fa-file-pdf', + default => 'fa-solid fa-file', + }; + } +} diff --git a/app/Http/Controllers/Bo/ClaimController.php b/app/Http/Controllers/Bo/ClaimController.php index 68e2caf..e6847b8 100644 --- a/app/Http/Controllers/Bo/ClaimController.php +++ b/app/Http/Controllers/Bo/ClaimController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Bo; +use App\Enums\Claims\ClaimExportFormat; use App\Enums\Claims\ClaimResponseType; use App\Enums\Claims\ClaimStatus; use App\Enums\Users\RoleEnum; @@ -11,7 +12,6 @@ use App\Http\Requests\Bo\Claims\ExportClaimRequest; use App\Http\Requests\Bo\Claims\SendClaimAnswerRequest; use App\Http\Requests\Bo\Claims\UpdateClaimRequest; use App\Http\Requests\Bo\PaginateModelsRequest; -use App\Jobs\ExportClaimsAsCsv; use App\Mail\ClaimAnswerMail; use App\Models\Brand; use App\Models\Claim; @@ -20,9 +20,12 @@ use App\Models\ClaimMessage; use App\Models\ClaimSubject; use App\Models\CustomerInfo; use App\Traits\Controllers\UpdateModelPublished; +use Barryvdh\DomPDF\Facade\Pdf; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Mail; +use Illuminate\Support\Str; +use Symfony\Component\HttpFoundation\StreamedResponse; use Uwil\LaravelCommon\Helpers\CollectionHelper; class ClaimController extends Controller @@ -67,8 +70,6 @@ class ClaimController extends Controller fn($q) => $q->whereNotIn('status', [ClaimStatus::treated, ClaimStatus::refused]) ); - // dd($query->toRawSql()); - /** @var string $search Search field */ $search = $request->search; if ($search) { @@ -95,7 +96,13 @@ class ClaimController extends Controller /** Custom pagination */ $claimModels = $query->simplePaginate($this->getPagination()); - $claimSubjectModels = ClaimSubject::all(); + $claimSubjectModels = ClaimSubject::query() + ->when( + $request->filled('brand'), + fn($q) => $q->whereHas('brand', fn($q) => $q->where('id', $request->brand)), + fn($q) => $q->whereHas('brand', fn($q) => $q->whereIn('id', $userModel->brands()->pluck('id'))) + ) + ->get(); return view('bo.pages.claims.index', compact('claimModels', 'search', 'searchFields', 'claimSubjectModels')); } @@ -220,28 +227,89 @@ class ClaimController extends Controller return \response()->json($models); } + + // * EXPORT + + /** + * CSV File headers + * + * @var array + */ + private $header = [ + "Prénom NOM", + "Email", + "Adresse", + "Date de création", + "Sujet", + "Statut", + "Message", + "Pièce jointe", + ]; + public function export(ExportClaimRequest $request) { $claims = Claim::query()->whereIn('id', $request->validated('claimList'))->get(); - $brandNames = Brand::query() - ->whereIn( - 'id', - \collect($claims) - ->pluck('brand_id') - ->unique() - )->pluck('name') - ->toArray(); + $format = ClaimExportFormat::from($request->validated('format')); - // dd($brandNames); - \dispatch(new ExportClaimsAsCsv($request->validated('email'), $brandNames, $claims)); + if ($format->equals(ClaimExportFormat::csv)) { + $csvlines[] = $this->header; + foreach ($claims as $claim) { + $csvlines[] = $this->fillLine($claim); + } - return \redirect() - ->back() - ->with('success', trans("Le traitement de l'export partiel a été lancé. Si vous n'avez pas recu de mail - cela signifie qu'une erreur est survenue et nous sommes au courant.")); + return new StreamedResponse(function() use ($csvlines) { + $this->array2csv($csvlines, ';'); + }, 200, [ + 'Content-Type' => 'text/csv', + 'Content-Disposition' => 'attachment; filename="export.csv"', + ]); + } elseif ($format->equals(ClaimExportFormat::pdf)) { + $pdf = Pdf::loadView('bo.pages.claims.pdf', [ + 'claimModels' => $claims + ]); + return $pdf->download('export.pdf'); + }; + return back()->with('error', __('Une erreur est survenue lors de l\'export. Veuillez réessayer en rafraîchissant la page.')); } + private function array2csv( + array $lines, + string $delimiter = ',', + string $enclosure = '"', + string $escape_char = "\\" + ){ + $f = fopen('php://output', 'w'); + // UTF-8 BOM. + $BOM = "\xEF\xBB\xBF"; + fwrite($f, $BOM); + foreach ($lines as $item) { + fputcsv($f, $item, $delimiter, $enclosure, $escape_char); + } + + fclose($f); + } + + /** + * fill one line for csv + * @param \App\Models\Claim $claim + * + * @return array + */ + private function fillLine(Claim $claim) + { + $oneline = [ + sprintf('%s %s', $claim->first_name, Str::upper($claim->last_name)), + $claim->email, + sprintf('%s, %s, %s', $claim->address, $claim->postcode, $claim->city), + $claim->created_at->toDateTimeString(), + $claim->claimSubject->label, + $claim->status->label(), + $claim->message, + asset($claim->file), + ]; + return $oneline; + } } diff --git a/app/Http/Requests/Bo/Claims/ExportClaimRequest.php b/app/Http/Requests/Bo/Claims/ExportClaimRequest.php index 5cc3a5c..37861a1 100644 --- a/app/Http/Requests/Bo/Claims/ExportClaimRequest.php +++ b/app/Http/Requests/Bo/Claims/ExportClaimRequest.php @@ -2,11 +2,9 @@ namespace App\Http\Requests\Bo\Claims; -use App\Enums\Claims\ClaimResponseType; -use App\Enums\Claims\ClaimStatus; -use App\Enums\Claims\ClaimType; +use App\Enums\Claims\ClaimExportFormat; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Validation\Rules\Enum; +use Illuminate\Validation\Rule; class ExportClaimRequest extends FormRequest { @@ -35,7 +33,10 @@ class ExportClaimRequest extends FormRequest public function rules(): array { return [ - 'email' => 'required|email', + 'format' => [ + 'required', + Rule::enum(ClaimExportFormat::class) + ], 'claimList' => 'required|array', 'claimList.*' => 'required|numeric|exists:claims,id', ]; diff --git a/app/Jobs/ExportClaimsAsCsv.php b/app/Jobs/ExportClaimsAsCsv.php deleted file mode 100644 index 0ce59dd..0000000 --- a/app/Jobs/ExportClaimsAsCsv.php +++ /dev/null @@ -1,134 +0,0 @@ -deleteDirectory('export_claims'); - $disk->makeDirectory('export_claims'); - - // Insertion de la ligne d'en-têtes. - $csvlines[] = $this->header; - foreach ($this->claims as $inscription) { - $csvlines[] = $this->fillLine($inscription); - } - - $data = $this->array2csv($csvlines, ";"); - - $uuid = Str::uuid(); - $fileName = date('d-m-Y') . '-' . $uuid . '.csv'; - - $disk->put("export_claims/{$fileName}", $data); - - if (!$disk->exists("export_claims/{$fileName}")) { - throw new \RuntimeException( - "The CSV file 'export_claims/{$fileName}' has not been created." - ); - } - - $brandNamesString = implode(', ', $this->brandNames); - - Mail::to($this->recipient)->send(new ExportClaims($fileName, $brandNamesString)); - } - - /** - * fill one line for csv - * @param \App\Models\Claim $claim - * - * @return array - * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh, Generic.Metrics.CyclomaticComplexity.MaxExceeded - */ - private function fillLine(Claim $claim) - { - // @phpcs:enable - $oneline = [ - sprintf('%s %s', $claim->first_name, Str::upper($claim->last_name)), - $claim->email, - $claim->address . "," . $claim->postcode . "," . $claim->city, - $claim->created_at->toDateTimeString(), - $claim->claimSubject->label, - $claim->status->label(), - $claim->message, - asset($claim->file), - ]; - return $oneline; - } - - /** - * converts an array to a csv stream - * - * @param array $data - * @param string $delimiter - * @param string $enclosure - * @param string $escape_char - * - * @return string - */ - private function array2csv( - array $data, - string $delimiter = ',', - string $enclosure = '"', - string $escape_char = "\\" - ) { - $f = fopen('php://memory', 'r+'); - - // UTF-8 BOM. - $BOM = "\xEF\xBB\xBF"; - fwrite($f, $BOM); - - foreach ($data as $item) { - fputcsv($f, $item, $delimiter, $enclosure, $escape_char); - } - rewind($f); - return stream_get_contents($f); - } -} diff --git a/app/Mail/ExportClaims.php b/app/Mail/ExportClaims.php deleted file mode 100644 index f8f5cf4..0000000 --- a/app/Mail/ExportClaims.php +++ /dev/null @@ -1,62 +0,0 @@ -brandName), - ); - } - - /** - * Get the message content definition. - */ - public function content(): Content - { - return new Content( - markdown: 'mail.export-claims', - text: 'mail.export-claims-plain' - ); - } - - /** - * Get the attachments for the message. - * - * @return array - */ - public function attachments(): array - { - return [ - Attachment::fromStorageDisk('export', "export_claims/{$this->fileName}") - ->as(sprintf( - 'export-reclas-%s.csv', - now()->format('Y-m-d') - )) - ]; - } -} diff --git a/app/Policies/ClaimPolicy.php b/app/Policies/ClaimPolicy.php index a6ea601..438594c 100644 --- a/app/Policies/ClaimPolicy.php +++ b/app/Policies/ClaimPolicy.php @@ -106,6 +106,18 @@ class ClaimPolicy return $this->checkOnlyMinAdminOrInUserBrands($authUser, $claim); } + /** + * Export a Claim. + * + * @param \App\Models\User $authUser + * @param \App\Models\Claim $claim + * @return boolean + */ + public function export(User $authUser, Claim $claim): bool + { + return $this->checkOnlyMinAdminOrInUserBrands($authUser, $claim); + } + /** * Check if the user an access a specific resource. * diff --git a/composer.json b/composer.json index 4d1d30c..96e5378 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "24slides/laravel-saml2": "^2.4", "arondeparon/laravel-request-sanitizer": "^5.0", "axlon/laravel-postal-code-validation": "^3.2", + "barryvdh/laravel-dompdf": "^3.1", "diglactic/laravel-breadcrumbs": "^9.0", "doctrine/dbal": "^3.0", "doctrine/inflector": "^2.0", diff --git a/composer.lock b/composer.lock index b076c98..b1e042f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c078e9a537be5c78427890f22fc24612", + "content-hash": "f04361d9a00c60112340a92b68293a68", "packages": [ { "name": "24slides/laravel-saml2", @@ -210,6 +210,83 @@ }, "time": "2024-09-10T15:23:59+00:00" }, + { + "name": "barryvdh/laravel-dompdf", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/laravel-dompdf.git", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "shasum": "" + }, + "require": { + "dompdf/dompdf": "^3.0", + "illuminate/support": "^9|^10|^11|^12", + "php": "^8.1" + }, + "require-dev": { + "larastan/larastan": "^2.7|^3.0", + "orchestra/testbench": "^7|^8|^9|^10", + "phpro/grumphp": "^2.5", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf", + "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf" + }, + "providers": [ + "Barryvdh\\DomPDF\\ServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Barryvdh\\DomPDF\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "A DOMPDF Wrapper for Laravel", + "keywords": [ + "dompdf", + "laravel", + "pdf" + ], + "support": { + "issues": "https://github.com/barryvdh/laravel-dompdf/issues", + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2025-02-13T15:07:54+00:00" + }, { "name": "brick/math", "version": "0.12.1", @@ -995,6 +1072,161 @@ ], "time": "2024-02-05T11:56:58+00:00" }, + { + "name": "dompdf/dompdf", + "version": "v3.1.4", + "source": { + "type": "git", + "url": "https://github.com/dompdf/dompdf.git", + "reference": "db712c90c5b9868df3600e64e68da62e78a34623" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/db712c90c5b9868df3600e64e68da62e78a34623", + "reference": "db712c90c5b9868df3600e64e68da62e78a34623", + "shasum": "" + }, + "require": { + "dompdf/php-font-lib": "^1.0.0", + "dompdf/php-svg-lib": "^1.0.0", + "ext-dom": "*", + "ext-mbstring": "*", + "masterminds/html5": "^2.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "ext-gd": "*", + "ext-json": "*", + "ext-zip": "*", + "mockery/mockery": "^1.3", + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" + }, + "suggest": { + "ext-gd": "Needed to process images", + "ext-gmagick": "Improves image processing performance", + "ext-imagick": "Improves image processing performance", + "ext-zlib": "Needed for pdf stream compression" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "The Dompdf Community", + "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" + } + ], + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "support": { + "issues": "https://github.com/dompdf/dompdf/issues", + "source": "https://github.com/dompdf/dompdf/tree/v3.1.4" + }, + "time": "2025-10-29T12:43:30+00:00" + }, + { + "name": "dompdf/php-font-lib", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-font-lib.git", + "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "The FontLib Community", + "homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/dompdf/php-font-lib", + "support": { + "issues": "https://github.com/dompdf/php-font-lib/issues", + "source": "https://github.com/dompdf/php-font-lib/tree/1.0.1" + }, + "time": "2024-12-02T14:37:59+00:00" + }, + { + "name": "dompdf/php-svg-lib", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0", + "sabberworm/php-css-parser": "^8.4" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Svg\\": "src/Svg" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The SvgLib Community", + "homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/dompdf/php-svg-lib", + "support": { + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0" + }, + "time": "2024-04-29T13:26:35+00:00" + }, { "name": "dragonmantank/cron-expression", "version": "v3.4.0", @@ -3330,6 +3562,73 @@ ], "time": "2024-12-08T08:18:47+00:00" }, + { + "name": "masterminds/html5", + "version": "2.10.0", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "fcf91eb64359852f00d921887b219479b4f21251" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251", + "reference": "fcf91eb64359852f00d921887b219479b4f21251", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.10.0" + }, + "time": "2025-07-25T09:04:22+00:00" + }, { "name": "mews/purifier", "version": "3.4.2", @@ -5115,6 +5414,72 @@ }, "time": "2024-11-20T21:13:56+00:00" }, + { + "name": "sabberworm/php-css-parser", + "version": "v8.9.0", + "source": { + "type": "git", + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/d8e916507b88e389e26d4ab03c904a082aa66bb9", + "reference": "d8e916507b88e389e26d4ab03c904a082aa66bb9", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + }, + "require-dev": { + "phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41", + "rawr/cross-data-providers": "^2.0.0" + }, + "suggest": { + "ext-mbstring": "for parsing UTF-8 CSS" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Sabberworm\\CSS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "support": { + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.9.0" + }, + "time": "2025-07-11T13:20:48+00:00" + }, { "name": "sentry/sentry", "version": "4.10.0", diff --git a/config/filesystems.php b/config/filesystems.php index 9f594c1..521ca82 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -67,14 +67,6 @@ return [ 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 'throw' => false, ], - - 'export' => [ - 'driver' => 'local', - 'root' => storage_path('app/export'), - 'visibility' => 'private', - 'throw' => true, - ], - ], /* diff --git a/resources/lang/en/crud.php b/resources/lang/en/crud.php index 1579b61..9c9ce57 100644 --- a/resources/lang/en/crud.php +++ b/resources/lang/en/crud.php @@ -10,6 +10,7 @@ return [ 'delete' => 'delete', 'save' => 'save', 'edit' => 'edit', + 'export' => 'export', ], 'helpers' => [ diff --git a/resources/lang/fr/crud.php b/resources/lang/fr/crud.php index 7e9529a..02d3b76 100644 --- a/resources/lang/fr/crud.php +++ b/resources/lang/fr/crud.php @@ -10,6 +10,7 @@ return [ 'delete' => 'supprimer', 'save' => 'sauvegarder', 'edit' => 'mettre à jour', + 'export' => 'exporter', ], 'helpers' => [ diff --git a/resources/ts/bo/pages/claims.ts b/resources/ts/bo/pages/claims.ts index e3736e4..7feb6db 100644 --- a/resources/ts/bo/pages/claims.ts +++ b/resources/ts/bo/pages/claims.ts @@ -1,17 +1,24 @@ +// Type for 'bootstrap modal show' event. Needed for 'relatedTarget'. +interface BootstrapModalShowEvent extends CustomEvent { + relatedTarget: HTMLElement; +} document.addEventListener("DOMContentLoaded", function () { - const exportForm = document.getElementById("claimExportForm"); - const exportFormBtn = document.getElementById("claimExportFormBtn"); - const exportFormBtnInside = document.getElementById("claimExportFormBtnInside"); + const exportFormModal = document.getElementById("exportModal"); + const claimListInputs = document.getElementsByClassName("claim-list-input"); - if (!exportForm || !exportFormBtn || !exportFormBtnInside || !(exportForm instanceof HTMLFormElement)) { + if (!exportFormModal || !claimListInputs) { return; } - exportFormBtn.addEventListener("click", function (e) { - e.preventDefault(); + exportFormModal.addEventListener("show.bs.modal", (event) => { + const customEvent = event as BootstrapModalShowEvent; + const button = customEvent.relatedTarget as HTMLElement; + const datas = button.getAttribute("data-bs-claim-list"); - exportFormBtnInside.click(); + for (const claimListInput of claimListInputs) { + (claimListInput as HTMLInputElement).value = String(datas); + } }); }); diff --git a/resources/ts/bo/utilities/fontawesome.ts b/resources/ts/bo/utilities/fontawesome.ts index c8d371e..9dc0c24 100644 --- a/resources/ts/bo/utilities/fontawesome.ts +++ b/resources/ts/bo/utilities/fontawesome.ts @@ -30,6 +30,9 @@ import { faEye, faEyeSlash, faFile, + faFileCsv, + faFileExport, + faFilePdf, faFolderOpen, faListUl, faPaintRoller, @@ -59,6 +62,9 @@ library.add( faEye, faEyeSlash, faFile, + faFileCsv, + faFileExport, + faFilePdf, faFolderOpen, faCrop, faQuestionCircle, diff --git a/resources/views/bo/modules/claim-tools.blade.php b/resources/views/bo/modules/claim-tools.blade.php index 53d2b71..91b5947 100644 --- a/resources/views/bo/modules/claim-tools.blade.php +++ b/resources/views/bo/modules/claim-tools.blade.php @@ -2,14 +2,14 @@ $selectedSubject = request()->subject ?? (isset($modelTable) ? Session::get("crud.$modelTable.subject") : null); @endphp -
-
-
-
+
{{-- SUBJECT SELECT --}} -
{{ __('L\'export sera envoyé en .csv à cette adresse mail.')}}
- - - -
+ @foreach(\App\Enums\Claims\ClaimExportFormat::cases() as $supportedFormat) +
+ @csrf + + + +
+ @endforeach
diff --git a/resources/views/bo/pages/claims/index-list.blade.php b/resources/views/bo/pages/claims/index-list.blade.php index 88809e4..fdc7228 100644 --- a/resources/views/bo/pages/claims/index-list.blade.php +++ b/resources/views/bo/pages/claims/index-list.blade.php @@ -60,6 +60,16 @@ @endcan + @can('export', $claimModel) + + + + @endcan @else diff --git a/resources/views/bo/pages/claims/pdf.blade.php b/resources/views/bo/pages/claims/pdf.blade.php new file mode 100644 index 0000000..a3fe59a --- /dev/null +++ b/resources/views/bo/pages/claims/pdf.blade.php @@ -0,0 +1,24 @@ + + +@foreach($claimModels as $claimModel) +

{{ __('Référence') }} : {{ $claimModel->reference }}

+

{{ __('Date de la demande') }} : {{ $claimModel->created_at->toDateString() }}

+

{{ __('Prénom NOM') }} : {{ $claimModel->first_name }} {{ str($claimModel->last_name)->upper() }}

+

{{ __('Email') }} : {{ $claimModel->email }}

+

{{ __('Adresse') }} : {{ sprintf('%s, %s, %s', $claimModel->address, $claimModel->postcode, $claimModel->city) }}

+

{{ __('Statut de la réclamation') }} : {{ $claimModel->status->label() }}

+

{{ __('Sujet de la réclamation') }} : {{ $claimModel->claimSubject->label }}

+

{{ __('Type de demande') }} : {{ $claimModel->type->label() }}

+

{{ __('Marque concernée') }} : {{ $claimModel->brand->name }}

+

{{ __('Message') }} : {{ $claimModel->message }}

+

{{ __('Voir la pièce jointe') }} : {{ __('Cliquez ici') }}

+ +@if (!$loop->last) +
+@endif + +@endforeach diff --git a/resources/views/mail/export-claims-plain.blade.php b/resources/views/mail/export-claims-plain.blade.php deleted file mode 100644 index 604c9ad..0000000 --- a/resources/views/mail/export-claims-plain.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -Bonjour, - -Vous trouverez ci-joint l'export des réclamations du {{ now()->isoFormat('DD\/MM\/YYYY à HH:mm') }} - -Ceci est un message automatique, ne pas répondre. diff --git a/resources/views/mail/export-claims.blade.php b/resources/views/mail/export-claims.blade.php deleted file mode 100644 index 80d4762..0000000 --- a/resources/views/mail/export-claims.blade.php +++ /dev/null @@ -1,10 +0,0 @@ -{{-- blade-formatter-disable --}} -@component('mail::layout') - -# {{ __('Bonjour,') }} - -{{ __('Vous trouverez ci-joint l\'export des réclamations du') }} {{ now()->isoFormat('DD\/MM\/YYYY à HH:mm') }} - -{{ __('Ceci est un message automatique, ne pas répondre.') }} - -@endcomponent diff --git a/routes/web-bo.php b/routes/web-bo.php index 2c729c6..68cb02b 100644 --- a/routes/web-bo.php +++ b/routes/web-bo.php @@ -93,7 +93,8 @@ Route::middleware(['throttle:web', 'admin-secure'])->prefix('bo')->name('bo.')-> // * CLAIMS. Route::resource('claims', ClaimController::class)->only(['index', 'edit', 'update']); Route::post('claims/{claim}/answer', [ClaimController::class, 'answer'])->name('claims.answer'); - Route::post('claims/export', [ClaimController::class, 'export'])->name('claims.export'); + Route::post('claims/export', [ClaimController::class, 'export']) + ->name('claims.export'); // * CLAIM SUBJECTS. Route::get('/{brand}/claim_subjects/json/paginate', [ClaimController::class, 'jsonClaimPaginateModels'])