update car create form

shift-build-2464
Nadim Salloum 2021-05-18 16:31:32 +02:00
parent 417760182e
commit 5ef66366ca
11 changed files with 2073 additions and 90 deletions

View File

@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Models\Brand; use App\Models\Brand;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
class BrandController extends Controller class BrandController extends Controller
{ {
@ -31,11 +32,16 @@ class BrandController extends Controller
* Store a newly created resource in storage. * Store a newly created resource in storage.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/ */
public function store(Request $request) public function store(Request $request)
{ {
// $brand = Brand::create(
$request->validate([
'name' => ['required', 'string', 'max:255'],
])
)->only('id', 'name');
return $brand;
} }
/** /**

View File

@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Models\Car; use App\Models\Car;
use Inertia\Inertia; use Inertia\Inertia;
use App\Models\Brand;
use App\Enums\InsuranceType; use App\Enums\InsuranceType;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
@ -97,7 +98,21 @@ class CarController extends Controller
*/ */
public function create() public function create()
{ {
return Inertia::render('Cars/Create'); return Inertia::render('Cars/Create', [
'brands' => Brand::all()->map(function ($brand) {
return [
'id' => $brand->id,
'name' => $brand->name,
'models' => $brand->carModels()->get()
->map(function ($carModel) {
return [
'id' => $carModel->id,
'name' => $carModel->name,
];
}),
];
}),
]);
} }
/** /**
@ -110,17 +125,17 @@ class CarController extends Controller
{ {
$car = Car::create( $car = Car::create(
$request->validate([ $request->validate([
'stammnummer' => ['unique', 'max:11'], 'stammnummer' => ['required', 'unique:cars', 'string', 'size:11', 'regex:/[0-9]{3}[.][0-9]{3}[.][0-9]{3}/i'],
'vin' => ['max:17'], 'vin' => ['required', 'unique:cars', 'string', 'size:17'],
'initial_date' => ['nullable', 'date'], 'initial_date' => ['nullable', 'date'],
'last_check_date' => ['nullable', 'date'], 'last_check_date' => ['nullable', 'date'],
'colour' => ['nullable', 'max:75'], 'colour' => ['nullable', 'max:75'],
// 'model_id' => ['nullable', 'max:150'], 'car_model_id' => ['required', 'exists:App\Models\CarModel,id'],
'kilometers' => ['nullable', 'max:75'], 'kilometers' => ['nullable', 'max:75'],
]) ])
); );
return Redirect::route('cars.edit', $car)->with('success', 'Kontakt erstellt.'); return Redirect::route('cars.edit', $car);
} }
@ -137,7 +152,8 @@ class CarController extends Controller
'id' => $car->id, 'id' => $car->id,
'stammnummer' => $car->stammnummer, 'stammnummer' => $car->stammnummer,
'vin' => $car->vin, 'vin' => $car->vin,
'car_model' => $car->carModel->only('name'), 'car_model' => $car->carModel,
'brand' => $car->brand,
'name' => $car->name, 'name' => $car->name,
'initial_date' => $car->initial_date, 'initial_date' => $car->initial_date,
'colour' => $car->colour, 'colour' => $car->colour,

View File

@ -35,7 +35,14 @@ class CarModelController extends Controller
*/ */
public function store(Request $request) public function store(Request $request)
{ {
// $model = CarModel::create(
$request->validate([
'name' => ['required', 'string', 'max:255'],
'brand_id' => ['required', 'exists:App\Models\Brand,id'],
])
)->only('id', 'name');
return $model;
} }
/** /**

View File

@ -10,7 +10,7 @@ class CarModel extends Model
use HasFactory; use HasFactory;
protected $fillable = [ protected $fillable = [
'car_model', 'name',
'brand_id', 'brand_id',
]; ];

15
package-lock.json generated
View File

@ -5,6 +5,7 @@
"packages": { "packages": {
"": { "": {
"dependencies": { "dependencies": {
"vue-multiselect": "^3.0.0-alpha.2",
"vue-unicons": "^3.2.1", "vue-unicons": "^3.2.1",
"vuex": "^4.0.0" "vuex": "^4.0.0"
}, },
@ -15389,6 +15390,15 @@
"node": ">=8.9.0" "node": ">=8.9.0"
} }
}, },
"node_modules/vue-multiselect": {
"version": "3.0.0-alpha.2",
"resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-3.0.0-alpha.2.tgz",
"integrity": "sha512-Xp9fGJECns45v+v8jXbCIsAkCybYkEg0lNwr7Z6HDUSMyx2TEIK2giipPE+qXiShEc1Ipn+ZtttH2iq9hwXP4Q==",
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/vue-style-loader": { "node_modules/vue-style-loader": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@ -28323,6 +28333,11 @@
} }
} }
}, },
"vue-multiselect": {
"version": "3.0.0-alpha.2",
"resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-3.0.0-alpha.2.tgz",
"integrity": "sha512-Xp9fGJECns45v+v8jXbCIsAkCybYkEg0lNwr7Z6HDUSMyx2TEIK2giipPE+qXiShEc1Ipn+ZtttH2iq9hwXP4Q=="
},
"vue-style-loader": { "vue-style-loader": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",

View File

@ -27,6 +27,7 @@
"vue-loader": "^16.1.2" "vue-loader": "^16.1.2"
}, },
"dependencies": { "dependencies": {
"vue-multiselect": "^3.0.0-alpha.2",
"vue-unicons": "^3.2.1", "vue-unicons": "^3.2.1",
"vuex": "^4.0.0" "vuex": "^4.0.0"
} }

1998
public/js/app.js vendored

File diff suppressed because one or more lines are too long

View File

@ -11,10 +11,29 @@
<template #form> <template #form>
<div class="col-span-6 sm:col-span-4"> <div class="col-span-6 sm:col-span-4">
<jet-label for="car_model_id" value="Modell" /> <jet-label for="brand" value="Marke" />
<jet-input id="car_model_id" type="text" class="mt-1 block w-full" v-model="form.car_model_id" ref="car_model_id" autocomplete="car_model_id" /> <multiselect v-model="brand" @SearchChange="updateBrandSearch" @select="updateCarModelsList" label="name" track-by="id" :options="brands" class="mt-1 block w-full" placeholder="Marke auswählen">
<jet-input-error :message="form.errors.car_model_id" class="mt-2" /> <template v-slot:noResult>
<span @click="addBrand">
<b>{{ brandSearch }}</b> als neue Marke speichern?
</span>
</template>
</multiselect>
</div> </div>
<div v-if="brand" class="col-span-6 sm:col-span-4">
<jet-label for="model" value="Modell" />
<multiselect label="name" track-by="id" v-model="model" @SearchChange="updateCarModelSearch" :options="carModels" class="mt-1 block w-full" placeholder="Modell auswählen">
<template v-slot:noResult>
<span @click="addCarModel">
<b>{{ modelSearch }}</b> als neues {{ brand.name }}-Modell speichern?
</span>
</template>
</multiselect>
<jet-input-error :message="form.errors.model" class="mt-2" />
</div>
<div class="col-span-6 sm:col-span-4"> <div class="col-span-6 sm:col-span-4">
<div class="grid grid-cols-12 gap-6"> <div class="grid grid-cols-12 gap-6">
<div class="col-span-12 sm:col-span-5"> <div class="col-span-12 sm:col-span-5">
@ -94,6 +113,7 @@ import Modal from '@/Jetstream/Modal.vue'
import JetActionMessage from '@/Jetstream/ActionMessage' import JetActionMessage from '@/Jetstream/ActionMessage'
import JetInputError from '@/Jetstream/InputError' import JetInputError from '@/Jetstream/InputError'
import JetFormSection from '@/Jetstream/FormSection' import JetFormSection from '@/Jetstream/FormSection'
import Multiselect from 'vue-multiselect'
export default { export default {
components: { components: {
@ -104,23 +124,60 @@ export default {
JetInput, JetInput,
JetInputError, JetInputError,
JetActionMessage, JetActionMessage,
Multiselect,
}, },
props: { props: {
form: Object, form: Object,
brands: Array,
meta: Object, meta: Object,
}, },
data() { data() {
return { return {
brand: this.form.brand,
brandSearch: null,
modelSearch: null,
carModels: [],
model: this.form.model,
} }
}, },
methods: { methods: {
submitForm() { submitForm() {
this.form.post(route(this.meta.link, this.form.data()), { this.form.post(route(this.meta.link, this.form.data()), {
preserveScroll: true, preserveScroll: true,
}); });
}, },
updateCarModelsList(brand) {
this.carModels = brand.models ?? [];
this.model = null;
},
updateBrandSearch(searchQuery, id) {
this.brandSearch = searchQuery
},
addBrand() {
axios.post(this.route('brands.store'), {
name: this.brandSearch,
}).then((response) => {
let newBrand = response.data;
this.brands.push(newBrand);
this.brand = newBrand;
});
},
updateCarModelSearch(searchQuery, id) {
this.modelSearch = searchQuery
},
addCarModel() {
axios.post(this.route('models.store'), {
name: this.modelSearch,
brand_id: this.brand.id,
}).then((response) => {
let newModel = response.data;
this.carModels.push(newModel);
this.model = newModel;
});
},
},
computed: {
}, },
} }
</script> </script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>

View File

@ -8,7 +8,7 @@
</template> </template>
<div> <div>
<car-form :form="form" :meta="meta"> <car-form :form="form" :meta="meta" :brands="brands">
<template #title>Neues Auto erfassen</template> <template #title>Neues Auto erfassen</template>
<template #description>...</template> <template #description>...</template>
</car-form> </car-form>
@ -27,6 +27,9 @@ export default {
BreadCrumb, BreadCrumb,
CarForm, CarForm,
}, },
props: {
brands: Array,
},
data() { data() {
return { return {
meta: { meta: {

View File

@ -8,15 +8,13 @@
</template> </template>
<div> <div>
<div class="max-w-7xl py-10 sm:px-6 lg:px-8"> <contact-form :form="form" :meta="meta">
<contact-form :form="form" :meta="meta"> <template #title>Kontaktinformationen</template>
<template #title>Kontaktinformationen</template> <template #description>
<template #description> Kontaktinformationen anschauen &amp; anpassen.
Kontaktinformationen anschauen &amp; anpassen. <contact-card :contact="computedContact" />
<contact-card :contact="computedContact" /> </template>
</template> </contact-form>
</contact-form>
</div>
</div> </div>
<div class="py-12"> <div class="py-12">
<div class="max-w-7xl sm:px-6 lg:px-8"> <div class="max-w-7xl sm:px-6 lg:px-8">

View File

@ -3,6 +3,8 @@
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use App\Http\Controllers\ContactController; use App\Http\Controllers\ContactController;
use App\Http\Controllers\CarController; use App\Http\Controllers\CarController;
use App\Http\Controllers\BrandController;
use App\Http\Controllers\CarModelController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Inertia\Inertia; use Inertia\Inertia;
@ -92,4 +94,12 @@ Route::put('cars/{car}', [CarController::class, 'update'])
Route::post('cars', [CarController::class, 'store']) Route::post('cars', [CarController::class, 'store'])
->name('cars.store') ->name('cars.store')
->middleware(['auth:sanctum', 'verified']);
Route::post('brands', [BrandController::class, 'store'])
->name('brands.store')
->middleware(['auth:sanctum', 'verified']);
Route::post('models', [CarModelController::class, 'store'])
->name('models.store')
->middleware(['auth:sanctum', 'verified']); ->middleware(['auth:sanctum', 'verified']);