From d8a3fa0b4ab21b8ebe60bdc882087e73ba99b7f0 Mon Sep 17 00:00:00 2001 From: Kamil Date: Sun, 17 Sep 2023 10:03:47 +0200 Subject: [PATCH 1/7] #5 - wip: crud for students --- .../Dashboard/StudentController.php | 34 +++++++++++++++++++ app/Http/Requests/StoreStudentRequest.php | 19 +++++++++++ app/Models/Student.php | 19 +++++++++++ database/factories/StudentFactory.php | 19 +++++++++++ ...023_09_17_075139_create_students_table.php | 25 ++++++++++++++ 5 files changed, 116 insertions(+) create mode 100644 app/Http/Controllers/Dashboard/StudentController.php create mode 100644 app/Http/Requests/StoreStudentRequest.php create mode 100644 app/Models/Student.php create mode 100644 database/factories/StudentFactory.php create mode 100644 database/migrations/2023_09_17_075139_create_students_table.php diff --git a/app/Http/Controllers/Dashboard/StudentController.php b/app/Http/Controllers/Dashboard/StudentController.php new file mode 100644 index 0000000..9b5a8a7 --- /dev/null +++ b/app/Http/Controllers/Dashboard/StudentController.php @@ -0,0 +1,34 @@ + ["required", "max:255"], + "surname" => ["required", "max:255"], + "index_number" => ["required", "integer", "unique:students,index_number"], + ]; + } +} diff --git a/app/Models/Student.php b/app/Models/Student.php new file mode 100644 index 0000000..9587683 --- /dev/null +++ b/app/Models/Student.php @@ -0,0 +1,19 @@ + fake()->name(), + "surname" => fake()->lastName(), + "index_number" => fake()->unique()->numberBetween(1, 10000), + ]; + } +} diff --git a/database/migrations/2023_09_17_075139_create_students_table.php b/database/migrations/2023_09_17_075139_create_students_table.php new file mode 100644 index 0000000..2a8046e --- /dev/null +++ b/database/migrations/2023_09_17_075139_create_students_table.php @@ -0,0 +1,25 @@ +id(); + $table->string("name"); + $table->string("surname"); + $table->integer("index_number"); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists("students"); + } +}; From 2c3cc6f18fe46a04b5770157ef241c81ddb5ad62 Mon Sep 17 00:00:00 2001 From: Kamil Date: Sun, 17 Sep 2023 23:05:21 +0200 Subject: [PATCH 2/7] #5 - added creating students --- .../Dashboard/StudentController.php | 19 +- app/Http/Middleware/HandleInertiaRequests.php | 11 ++ app/Http/Requests/StoreStudentRequest.php | 2 +- config/app.php | 2 +- lang/en/auth.php | 20 ++ lang/en/pagination.php | 19 ++ lang/en/passwords.php | 22 +++ lang/en/validation.php | 185 ++++++++++++++++++ lang/pl/pagination.php | 8 + lang/pl/validation.php | 124 ++++++++++++ package-lock.json | 74 +++++-- package.json | 5 +- resources/css/app.css | 2 + resources/js/Layouts/DashboardLayout.vue | 30 +++ resources/js/Pages/Dashboard/Home.vue | 2 +- .../js/Pages/Dashboard/Student/Create.vue | 68 +++++++ .../js/Pages/Dashboard/Student/Index.vue | 60 ++++++ resources/js/Pages/Public/Home.vue | 2 +- .../js/Shared/Components/Buttons/Button.vue | 33 ++++ .../Components/Buttons/SecondaryButton.vue | 25 +++ .../Components/Buttons/SubmitButton.vue | 24 +++ resources/js/Shared/Components/Pagination.vue | 20 ++ resources/js/Shared/Components/Section.vue | 5 + .../js/Shared/Components/Table/TableCell.vue | 5 + .../Shared/Components/Table/TableHeader.vue | 8 + .../js/Shared/Components/Table/TableRow.vue | 5 + .../Shared/Components/Table/TableWrapper.vue | 28 +++ resources/js/Shared/Forms/FormError.vue | 14 ++ resources/js/Shared/Forms/FormGroup.vue | 14 ++ resources/js/Shared/Forms/FormLabel.vue | 21 ++ resources/js/Shared/Forms/TextInput.vue | 31 +++ resources/js/app.js | 9 +- routes/web.php | 10 + 33 files changed, 882 insertions(+), 25 deletions(-) create mode 100644 lang/en/auth.php create mode 100644 lang/en/pagination.php create mode 100644 lang/en/passwords.php create mode 100644 lang/en/validation.php create mode 100644 lang/pl/pagination.php create mode 100644 lang/pl/validation.php create mode 100644 resources/js/Pages/Dashboard/Student/Create.vue create mode 100644 resources/js/Pages/Dashboard/Student/Index.vue create mode 100644 resources/js/Shared/Components/Buttons/Button.vue create mode 100644 resources/js/Shared/Components/Buttons/SecondaryButton.vue create mode 100644 resources/js/Shared/Components/Buttons/SubmitButton.vue create mode 100644 resources/js/Shared/Components/Pagination.vue create mode 100644 resources/js/Shared/Components/Section.vue create mode 100644 resources/js/Shared/Components/Table/TableCell.vue create mode 100644 resources/js/Shared/Components/Table/TableHeader.vue create mode 100644 resources/js/Shared/Components/Table/TableRow.vue create mode 100644 resources/js/Shared/Components/Table/TableWrapper.vue create mode 100644 resources/js/Shared/Forms/FormError.vue create mode 100644 resources/js/Shared/Forms/FormGroup.vue create mode 100644 resources/js/Shared/Forms/FormLabel.vue create mode 100644 resources/js/Shared/Forms/TextInput.vue diff --git a/app/Http/Controllers/Dashboard/StudentController.php b/app/Http/Controllers/Dashboard/StudentController.php index 9b5a8a7..2b2165b 100644 --- a/app/Http/Controllers/Dashboard/StudentController.php +++ b/app/Http/Controllers/Dashboard/StudentController.php @@ -5,19 +5,32 @@ namespace App\Http\Controllers\Dashboard; use App\Http\Controllers\Controller; +use App\Http\Requests\StoreStudentRequest; +use App\Models\Student; +use Illuminate\Http\RedirectResponse; +use Inertia\Response; class StudentController extends Controller { - public function index(): void + public function index(): Response { + return inertia("Dashboard/Student/Index", [ + "students" => Student::query()->paginate(), + ]); } - public function create(): void + public function create(): Response { + return inertia("Dashboard/Student/Create"); } - public function store(): void + public function store(StoreStudentRequest $request): RedirectResponse { + Student::query()->create($request->validated()); + + return redirect() + ->route("students.index") + ->with("success", "Dodano studenta"); } public function edit(): void diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 87d7f2b..8c88947 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -4,6 +4,7 @@ namespace App\Http\Middleware; +use Closure; use Illuminate\Http\Request; use Inertia\Middleware; @@ -19,6 +20,16 @@ public function version(Request $request): ?string public function share(Request $request): array { return array_merge(parent::share($request), [ + "flash" => $this->getFlashedData($request), ]); } + + protected function getFlashedData(Request $request): Closure + { + return fn(): array => [ + "success" => $request->session()->get("success"), + "error" => $request->session()->get("error"), + "info" => $request->session()->get("info"), + ]; + } } diff --git a/app/Http/Requests/StoreStudentRequest.php b/app/Http/Requests/StoreStudentRequest.php index f828c0a..a119941 100644 --- a/app/Http/Requests/StoreStudentRequest.php +++ b/app/Http/Requests/StoreStudentRequest.php @@ -13,7 +13,7 @@ public function rules(): array return [ "name" => ["required", "max:255"], "surname" => ["required", "max:255"], - "index_number" => ["required", "integer", "unique:students,index_number"], + "index_number" => ["required", "numeric", "max:999999", "unique:students,index_number"], ]; } } diff --git a/config/app.php b/config/app.php index 2705439..8b21d9f 100644 --- a/config/app.php +++ b/config/app.php @@ -18,7 +18,7 @@ "url" => env("APP_URL", "http://localhost"), "asset_url" => env("ASSET_URL"), "timezone" => "UTC", - "locale" => "en", + "locale" => "pl", "fallback_locale" => "en", "faker_locale" => "en_US", "key" => env("APP_KEY"), diff --git a/lang/en/auth.php b/lang/en/auth.php new file mode 100644 index 0000000..c939840 --- /dev/null +++ b/lang/en/auth.php @@ -0,0 +1,20 @@ + "These credentials do not match our records.", + "password" => "The provided password is incorrect.", + "throttle" => "Too many login attempts. Please try again in :seconds seconds.", +]; diff --git a/lang/en/pagination.php b/lang/en/pagination.php new file mode 100644 index 0000000..5323c9f --- /dev/null +++ b/lang/en/pagination.php @@ -0,0 +1,19 @@ + "« Previous", + "next" => "Next »", +]; diff --git a/lang/en/passwords.php b/lang/en/passwords.php new file mode 100644 index 0000000..2a46fa6 --- /dev/null +++ b/lang/en/passwords.php @@ -0,0 +1,22 @@ + "Your password has been reset.", + "sent" => "We have emailed your password reset link.", + "throttled" => "Please wait before retrying.", + "token" => "This password reset token is invalid.", + "user" => "We can't find a user with that email address.", +]; diff --git a/lang/en/validation.php b/lang/en/validation.php new file mode 100644 index 0000000..868f35e --- /dev/null +++ b/lang/en/validation.php @@ -0,0 +1,185 @@ + "The :attribute field must be accepted.", + "accepted_if" => "The :attribute field must be accepted when :other is :value.", + "active_url" => "The :attribute field must be a valid URL.", + "after" => "The :attribute field must be a date after :date.", + "after_or_equal" => "The :attribute field must be a date after or equal to :date.", + "alpha" => "The :attribute field must only contain letters.", + "alpha_dash" => "The :attribute field must only contain letters, numbers, dashes, and underscores.", + "alpha_num" => "The :attribute field must only contain letters and numbers.", + "array" => "The :attribute field must be an array.", + "ascii" => "The :attribute field must only contain single-byte alphanumeric characters and symbols.", + "before" => "The :attribute field must be a date before :date.", + "before_or_equal" => "The :attribute field must be a date before or equal to :date.", + "between" => [ + "array" => "The :attribute field must have between :min and :max items.", + "file" => "The :attribute field must be between :min and :max kilobytes.", + "numeric" => "The :attribute field must be between :min and :max.", + "string" => "The :attribute field must be between :min and :max characters.", + ], + "boolean" => "The :attribute field must be true or false.", + "can" => "The :attribute field contains an unauthorized value.", + "confirmed" => "The :attribute field confirmation does not match.", + "current_password" => "The password is incorrect.", + "date" => "The :attribute field must be a valid date.", + "date_equals" => "The :attribute field must be a date equal to :date.", + "date_format" => "The :attribute field must match the format :format.", + "decimal" => "The :attribute field must have :decimal decimal places.", + "declined" => "The :attribute field must be declined.", + "declined_if" => "The :attribute field must be declined when :other is :value.", + "different" => "The :attribute field and :other must be different.", + "digits" => "The :attribute field must be :digits digits.", + "digits_between" => "The :attribute field must be between :min and :max digits.", + "dimensions" => "The :attribute field has invalid image dimensions.", + "distinct" => "The :attribute field has a duplicate value.", + "doesnt_end_with" => "The :attribute field must not end with one of the following: :values.", + "doesnt_start_with" => "The :attribute field must not start with one of the following: :values.", + "email" => "The :attribute field must be a valid email address.", + "ends_with" => "The :attribute field must end with one of the following: :values.", + "enum" => "The selected :attribute is invalid.", + "exists" => "The selected :attribute is invalid.", + "file" => "The :attribute field must be a file.", + "filled" => "The :attribute field must have a value.", + "gt" => [ + "array" => "The :attribute field must have more than :value items.", + "file" => "The :attribute field must be greater than :value kilobytes.", + "numeric" => "The :attribute field must be greater than :value.", + "string" => "The :attribute field must be greater than :value characters.", + ], + "gte" => [ + "array" => "The :attribute field must have :value items or more.", + "file" => "The :attribute field must be greater than or equal to :value kilobytes.", + "numeric" => "The :attribute field must be greater than or equal to :value.", + "string" => "The :attribute field must be greater than or equal to :value characters.", + ], + "image" => "The :attribute field must be an image.", + "in" => "The selected :attribute is invalid.", + "in_array" => "The :attribute field must exist in :other.", + "integer" => "The :attribute field must be an integer.", + "ip" => "The :attribute field must be a valid IP address.", + "ipv4" => "The :attribute field must be a valid IPv4 address.", + "ipv6" => "The :attribute field must be a valid IPv6 address.", + "json" => "The :attribute field must be a valid JSON string.", + "lowercase" => "The :attribute field must be lowercase.", + "lt" => [ + "array" => "The :attribute field must have less than :value items.", + "file" => "The :attribute field must be less than :value kilobytes.", + "numeric" => "The :attribute field must be less than :value.", + "string" => "The :attribute field must be less than :value characters.", + ], + "lte" => [ + "array" => "The :attribute field must not have more than :value items.", + "file" => "The :attribute field must be less than or equal to :value kilobytes.", + "numeric" => "The :attribute field must be less than or equal to :value.", + "string" => "The :attribute field must be less than or equal to :value characters.", + ], + "mac_address" => "The :attribute field must be a valid MAC address.", + "max" => [ + "array" => "The :attribute field must not have more than :max items.", + "file" => "The :attribute field must not be greater than :max kilobytes.", + "numeric" => "The :attribute field must not be greater than :max.", + "string" => "The :attribute field must not be greater than :max characters.", + ], + "max_digits" => "The :attribute field must not have more than :max digits.", + "mimes" => "The :attribute field must be a file of type: :values.", + "mimetypes" => "The :attribute field must be a file of type: :values.", + "min" => [ + "array" => "The :attribute field must have at least :min items.", + "file" => "The :attribute field must be at least :min kilobytes.", + "numeric" => "The :attribute field must be at least :min.", + "string" => "The :attribute field must be at least :min characters.", + ], + "min_digits" => "The :attribute field must have at least :min digits.", + "missing" => "The :attribute field must be missing.", + "missing_if" => "The :attribute field must be missing when :other is :value.", + "missing_unless" => "The :attribute field must be missing unless :other is :value.", + "missing_with" => "The :attribute field must be missing when :values is present.", + "missing_with_all" => "The :attribute field must be missing when :values are present.", + "multiple_of" => "The :attribute field must be a multiple of :value.", + "not_in" => "The selected :attribute is invalid.", + "not_regex" => "The :attribute field format is invalid.", + "numeric" => "The :attribute field must be a number.", + "password" => [ + "letters" => "The :attribute field must contain at least one letter.", + "mixed" => "The :attribute field must contain at least one uppercase and one lowercase letter.", + "numbers" => "The :attribute field must contain at least one number.", + "symbols" => "The :attribute field must contain at least one symbol.", + "uncompromised" => "The given :attribute has appeared in a data leak. Please choose a different :attribute.", + ], + "present" => "The :attribute field must be present.", + "prohibited" => "The :attribute field is prohibited.", + "prohibited_if" => "The :attribute field is prohibited when :other is :value.", + "prohibited_unless" => "The :attribute field is prohibited unless :other is in :values.", + "prohibits" => "The :attribute field prohibits :other from being present.", + "regex" => "The :attribute field format is invalid.", + "required" => "The :attribute field is required.", + "required_array_keys" => "The :attribute field must contain entries for: :values.", + "required_if" => "The :attribute field is required when :other is :value.", + "required_if_accepted" => "The :attribute field is required when :other is accepted.", + "required_unless" => "The :attribute field is required unless :other is in :values.", + "required_with" => "The :attribute field is required when :values is present.", + "required_with_all" => "The :attribute field is required when :values are present.", + "required_without" => "The :attribute field is required when :values is not present.", + "required_without_all" => "The :attribute field is required when none of :values are present.", + "same" => "The :attribute field must match :other.", + "size" => [ + "array" => "The :attribute field must contain :size items.", + "file" => "The :attribute field must be :size kilobytes.", + "numeric" => "The :attribute field must be :size.", + "string" => "The :attribute field must be :size characters.", + ], + "starts_with" => "The :attribute field must start with one of the following: :values.", + "string" => "The :attribute field must be a string.", + "timezone" => "The :attribute field must be a valid timezone.", + "unique" => "The :attribute has already been taken.", + "uploaded" => "The :attribute failed to upload.", + "uppercase" => "The :attribute field must be uppercase.", + "url" => "The :attribute field must be a valid URL.", + "ulid" => "The :attribute field must be a valid ULID.", + "uuid" => "The :attribute field must be a valid UUID.", + + /* + |-------------------------------------------------------------------------- + | Custom Validation Language Lines + |-------------------------------------------------------------------------- + | + | Here you may specify custom validation messages for attributes using the + | convention "attribute.rule" to name the lines. This makes it quick to + | specify a specific custom language line for a given attribute rule. + | + */ + + "custom" => [ + "attribute-name" => [ + "rule-name" => "custom-message", + ], + ], + + /* + |-------------------------------------------------------------------------- + | Custom Validation Attributes + |-------------------------------------------------------------------------- + | + | The following language lines are used to swap our attribute placeholder + | with something more reader friendly such as "E-Mail Address" instead + | of "email". This simply helps us make our message more expressive. + | + */ + + "attributes" => [], +]; diff --git a/lang/pl/pagination.php b/lang/pl/pagination.php new file mode 100644 index 0000000..49e8df0 --- /dev/null +++ b/lang/pl/pagination.php @@ -0,0 +1,8 @@ + "Następna", + "previous" => "Poprzednia", +]; diff --git a/lang/pl/validation.php b/lang/pl/validation.php new file mode 100644 index 0000000..8035d8d --- /dev/null +++ b/lang/pl/validation.php @@ -0,0 +1,124 @@ + "Pole :attribute musi zostać zaakceptowane.", + "active_url" => "Pole :attribute jest nieprawidłowym adresem URL.", + "after" => "Pole :attribute musi być datą późniejszą od :date.", + "after_or_equal" => "Pole :attribute musi być datą nie wcześniejszą niż :date.", + "alpha" => "Pole :attribute może zawierać jedynie litery.", + "alpha_dash" => "Pole :attribute może zawierać jedynie litery, cyfry i myślniki.", + "alpha_num" => "Pole :attribute może zawierać jedynie litery i cyfry.", + "array" => "Pole :attribute musi być tablicą.", + "attached" => "Ten :attribute jest już dołączony.", + "before" => "Pole :attribute musi być datą wcześniejszą od :date.", + "before_or_equal" => "Pole :attribute musi być datą nie późniejszą niż :date.", + "between" => [ + "array" => "Pole :attribute musi składać się z :min - :max elementów.", + "file" => "Pole :attribute musi zawierać się w granicach :min - :max kilobajtów.", + "numeric" => "Pole :attribute musi zawierać się w granicach :min - :max.", + "string" => "Pole :attribute musi zawierać się w granicach :min - :max znaków.", + ], + "boolean" => "Pole :attribute musi mieć wartość logiczną prawda albo fałsz.", + "confirmed" => "Potwierdzenie pola :attribute nie zgadza się.", + "current_password" => "Hasło jest nieprawidłowe.", + "date" => "Pole :attribute nie jest prawidłową datą.", + "date_equals" => "Pole :attribute musi być datą równą :date.", + "date_format" => "Pole :attribute nie jest w formacie :format.", + "different" => "Pole :attribute oraz :other muszą się różnić.", + "digits" => "Pole :attribute musi składać się z :digits cyfr.", + "digits_between" => "Pole :attribute musi mieć od :min do :max cyfr.", + "dimensions" => "Pole :attribute ma niepoprawne wymiary.", + "distinct" => "Pole :attribute ma zduplikowane wartości.", + "email" => "Pole :attribute nie jest poprawnym adresem e-mail.", + "ends_with" => "Pole :attribute musi kończyć się jedną z następujących wartości: :values.", + "exists" => "Zaznaczone pole :attribute jest nieprawidłowe.", + "file" => "Pole :attribute musi być plikiem.", + "filled" => "Pole :attribute nie może być puste.", + "gt" => [ + "array" => "Pole :attribute musi mieć więcej niż :value elementów.", + "file" => "Pole :attribute musi być większe niż :value kilobajtów.", + "numeric" => "Pole :attribute musi być większe niż :value.", + "string" => "Pole :attribute musi być dłuższe niż :value znaków.", + ], + "gte" => [ + "array" => "Pole :attribute musi mieć :value lub więcej elementów.", + "file" => "Pole :attribute musi być większe lub równe :value kilobajtów.", + "numeric" => "Pole :attribute musi być większe lub równe :value.", + "string" => "Pole :attribute musi być dłuższe lub równe :value znaków.", + ], + "image" => "Pole :attribute musi być obrazkiem.", + "in" => "Zaznaczony element :attribute jest nieprawidłowy.", + "in_array" => "Pole :attribute nie znajduje się w :other.", + "integer" => "Pole :attribute musi być liczbą całkowitą.", + "ip" => "Pole :attribute musi być prawidłowym adresem IP.", + "ipv4" => "Pole :attribute musi być prawidłowym adresem IPv4.", + "ipv6" => "Pole :attribute musi być prawidłowym adresem IPv6.", + "json" => "Pole :attribute musi być poprawnym ciągiem znaków JSON.", + "lt" => [ + "array" => "Pole :attribute musi mieć mniej niż :value elementów.", + "file" => "Pole :attribute musi być mniejsze niż :value kilobajtów.", + "numeric" => "Pole :attribute musi być mniejsze niż :value.", + "string" => "Pole :attribute musi być krótsze niż :value znaków.", + ], + "lte" => [ + "array" => "Pole :attribute musi mieć :value lub mniej elementów.", + "file" => "Pole :attribute musi być mniejsze lub równe :value kilobajtów.", + "numeric" => "Pole :attribute musi być mniejsze lub równe :value.", + "string" => "Pole :attribute musi być krótsze lub równe :value znaków.", + ], + "max" => [ + "array" => "Pole :attribute nie może mieć więcej niż :max elementów.", + "file" => "Pole :attribute nie może być większe niż :max kilobajtów.", + "numeric" => "Pole :attribute nie może być większe niż :max.", + "string" => "Pole :attribute nie może być dłuższe niż :max znaków.", + ], + "mimes" => "Pole :attribute musi być plikiem typu :values.", + "mimetypes" => "Pole :attribute musi być plikiem typu :values.", + "min" => [ + "array" => "Pole :attribute musi mieć przynajmniej :min elementów.", + "file" => "Pole :attribute musi mieć przynajmniej :min kilobajtów.", + "numeric" => "Pole :attribute musi być nie mniejsze od :min.", + "string" => "Pole :attribute musi mieć przynajmniej :min znaków.", + ], + "multiple_of" => "Pole :attribute musi być wielokrotnością wartości :value", + "not_in" => "Zaznaczony :attribute jest nieprawidłowy.", + "not_regex" => "Format pola :attribute jest nieprawidłowy.", + "numeric" => "Pole :attribute musi być liczbą.", + "password" => "Hasło jest nieprawidłowe.", + "present" => "Pole :attribute musi być obecne.", + "prohibited" => "Pole :attribute jest zabronione.", + "prohibited_if" => "Pole :attribute jest zabronione, gdy :other to :value.", + "prohibited_unless" => "Pole :attribute jest zabronione, chyba że :other jest w :values.", + "regex" => "Format pola :attribute jest nieprawidłowy.", + "relatable" => "Ten :attribute może nie być powiązany z tym zasobem.", + "required" => "Pole :attribute jest wymagane.", + "required_if" => "Pole :attribute jest wymagane gdy :other ma wartość :value.", + "required_unless" => "Pole :attribute jest wymagane jeżeli :other nie znajduje się w :values.", + "required_with" => "Pole :attribute jest wymagane gdy :values jest obecny.", + "required_with_all" => "Pole :attribute jest wymagane gdy wszystkie :values są obecne.", + "required_without" => "Pole :attribute jest wymagane gdy :values nie jest obecny.", + "required_without_all" => "Pole :attribute jest wymagane gdy żadne z :values nie są obecne.", + "same" => "Pole :attribute i :other muszą być takie same.", + "size" => [ + "array" => "Pole :attribute musi zawierać :size elementów.", + "file" => "Pole :attribute musi mieć :size kilobajtów.", + "numeric" => "Pole :attribute musi mieć :size.", + "string" => "Pole :attribute musi mieć :size znaków.", + ], + "starts_with" => "Pole :attribute musi zaczynać się jedną z następujących wartości: :values.", + "string" => "Pole :attribute musi być ciągiem znaków.", + "timezone" => "Pole :attribute musi być prawidłową strefą czasową.", + "unique" => "Taki :attribute już występuje.", + "uploaded" => "Nie udało się wgrać pliku :attribute.", + "url" => "Format pola :attribute jest nieprawidłowy.", + "uuid" => "Pole :attribute musi być poprawnym identyfikatorem UUID.", + "custom" => [ + ], + "attributes" => [ + "name" => "imię", + "surname" => "nazwisko", + "index_number" => "numer indeksu", + ], +]; diff --git a/package-lock.json b/package-lock.json index 46ff3ff..53b1043 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,8 @@ "dependencies": { "@headlessui/vue": "^1.7.16", "@heroicons/vue": "^2.0.18", + "@inertiajs/inertia": "^0.11.0", + "@inertiajs/inertia-vue3": "^0.6.0", "@inertiajs/vue3": "^1.0.11", "@tailwindcss/forms": "^0.5.6", "@tailwindcss/typography": "^0.5.10", @@ -15,7 +17,8 @@ "laravel-vite-plugin": "^0.8.0", "lodash": "^4.17.21", "tailwindcss": "^3.3.3", - "vue": "^3.3.4" + "vue": "^3.3.4", + "vue-toastification": "^2.0.0-rc.5" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^6.7.0", @@ -509,6 +512,37 @@ "qs": "^6.9.0" } }, + "node_modules/@inertiajs/inertia": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@inertiajs/inertia/-/inertia-0.11.1.tgz", + "integrity": "sha512-btmV53c54oW4Z9XF0YyTdIUnM7ue0ONy3/KJOz6J1C5CYIwimiKfDMpz8ZbGJuxS+SPdOlNsqj2ZhlHslpJRZg==", + "dependencies": { + "axios": "^0.21.1", + "deepmerge": "^4.0.0", + "qs": "^6.9.0" + } + }, + "node_modules/@inertiajs/inertia-vue3": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@inertiajs/inertia-vue3/-/inertia-vue3-0.6.0.tgz", + "integrity": "sha512-qhPBtd/G0VS7vVVbYw1rrqKB6JqRusxqt+5ec2GLmK6t7fTlBBnZ3KsakmGZLSM1m1OGkNcfn4ifmCk3zfA8RQ==", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "peerDependencies": { + "@inertiajs/inertia": "^0.11.0", + "vue": "^3.0.0" + } + }, + "node_modules/@inertiajs/inertia/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, "node_modules/@inertiajs/vue3": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@inertiajs/vue3/-/vue3-1.0.11.tgz", @@ -623,9 +657,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", + "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", "dev": true }, "node_modules/@types/semver": { @@ -1408,9 +1442,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.520", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.520.tgz", - "integrity": "sha512-Frfus2VpYADsrh1lB3v/ft/WVFlVzOIm+Q0p7U7VqHI6qr7NWHYKe+Wif3W50n7JAFoBsWVsoU0+qDks6WQ60g==", + "version": "1.4.523", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.523.tgz", + "integrity": "sha512-9AreocSUWnzNtvLcbpng6N+GkXnCcBR80IQkxRC9Dfdyg4gaWNUPBujAHUpKkiUkoSoR9UlhA4zD/IgBklmhzg==", "dev": true }, "node_modules/esbuild": { @@ -1784,9 +1818,9 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/follow-redirects": { @@ -2765,9 +2799,9 @@ } }, "node_modules/resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -2814,9 +2848,9 @@ } }, "node_modules/rollup": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.1.tgz", - "integrity": "sha512-c+ebvQz0VIH4KhhCpDsI+Bik0eT8ZFEVZEYw0cGMVqIP8zc+gnwl7iXCamTw7vzv2MeuZFZfdx5JJIq+ehzDlg==", + "version": "3.29.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.2.tgz", + "integrity": "sha512-CJouHoZ27v6siztc21eEQGo0kIcE5D1gVPA571ez0mMYb25LGYGKnVNXpEj5MGlepmDWGXNjDB5q7uNiPHC11A==", "bin": { "rollup": "dist/bin/rollup" }, @@ -3288,6 +3322,14 @@ "eslint": ">=6.0.0" } }, + "node_modules/vue-toastification": { + "version": "2.0.0-rc.5", + "resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz", + "integrity": "sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA==", + "peerDependencies": { + "vue": "^3.0.2" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 38a3997..23fe05d 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "dependencies": { "@headlessui/vue": "^1.7.16", "@heroicons/vue": "^2.0.18", + "@inertiajs/inertia": "^0.11.0", + "@inertiajs/inertia-vue3": "^0.6.0", "@inertiajs/vue3": "^1.0.11", "@tailwindcss/forms": "^0.5.6", "@tailwindcss/typography": "^0.5.10", @@ -17,7 +19,8 @@ "laravel-vite-plugin": "^0.8.0", "lodash": "^4.17.21", "tailwindcss": "^3.3.3", - "vue": "^3.3.4" + "vue": "^3.3.4", + "vue-toastification": "^2.0.0-rc.5" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^6.7.0", diff --git a/resources/css/app.css b/resources/css/app.css index b5c61c9..5aece88 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1,3 +1,5 @@ +@import 'vue-toastification/dist/index.css'; + @tailwind base; @tailwind components; @tailwind utilities; diff --git a/resources/js/Layouts/DashboardLayout.vue b/resources/js/Layouts/DashboardLayout.vue index 26c5bc5..4baaaf8 100644 --- a/resources/js/Layouts/DashboardLayout.vue +++ b/resources/js/Layouts/DashboardLayout.vue @@ -18,6 +18,18 @@ import { CodeBracketSquareIcon, Cog6ToothIcon, } from '@heroicons/vue/24/outline' +import { watch } from 'vue' +import { useToast } from 'vue-toastification' + +const toast = useToast() +const props = defineProps({ + flash: { + type: Object, + default () { + return Object + }, + }, +}) const navigation = [ { @@ -50,6 +62,24 @@ const navigation = [ ] const sidebarOpen = ref(false) + +watch(() => props.flash, (flash) => { + if (!flash) { + return + } + + if (flash.success) { + toast.success(flash.success) + } + + if (flash.info) { + toast.info(flash.info) + } + + if (flash.error) { + toast.error(flash.error) + } +}, { immediate: true })