Skip to content

Commit 651db10

Browse files
authored
Form components (#30)
1 parent cc87e46 commit 651db10

File tree

89 files changed

+7151
-1635
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+7151
-1635
lines changed

.gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
/.gitignore export-ignore
88
/phpunit.xml.dist export-ignore
99
/art export-ignore
10+
/app export-ignore
1011
/docs export-ignore
1112
/tests export-ignore
1213
/.editorconfig export-ignore

.github/workflows/run-tests.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ jobs:
8080
run: |
8181
cd app
8282
sed -i -e "s|SPLADE_SSR_ENABLED=false|SPLADE_SSR_ENABLED=true|g" .env
83-
node bootstrap/ssr/ssr.js &
83+
node bootstrap/ssr/ssr.mjs &
8484
if: matrix.ssr == true
8585

8686
- name: Run Laravel Server
@@ -172,7 +172,9 @@ jobs:
172172
php artisan splade:install
173173
174174
- name: Install NPM dependencies
175-
run: npm i
175+
run: |
176+
npm i
177+
npm i autosize choices.js flatpickr
176178
177179
- name: Remove installed Splade and copy front-end build from Checkout (Unix)
178180
run: |

app/.env.example

+1
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,5 @@ VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
4646
VITE_PUSHER_HOST="${PUSHER_HOST}"
4747
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
4848

49+
DEBUGBAR_ENABLED=false
4950
SPLADE_SSR_ENABLED=false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Models\Dummy;
6+
use Illuminate\Http\Request;
7+
use Illuminate\Support\Fluent;
8+
use Illuminate\Validation\Rule;
9+
use ProtoneMedia\Splade\Components\Form;
10+
use ProtoneMedia\Splade\Components\Form\Input;
11+
use ProtoneMedia\Splade\Components\Form\Select;
12+
13+
class FormComponentsController
14+
{
15+
private function countries(): array
16+
{
17+
return collect(json_decode(file_get_contents(resource_path('iso3166.json'))))
18+
->keyBy->{'alpha-2'}
19+
->map->name
20+
->all();
21+
}
22+
23+
public function simple()
24+
{
25+
return view('form.components.simple', ['countries' => $this->countries()]);
26+
}
27+
28+
public function defaults()
29+
{
30+
Select::defaultChoices();
31+
32+
Input::defaultDateFormat('d-m-Y');
33+
Input::defaultTimeFormat('i:H');
34+
Input::defaultDatetimeFormat('d-m-Y H:i');
35+
Input::defaultFlatpickr(['showMonths' => 2, 'defaultHour' => 20]);
36+
37+
return view('form.components.simple', ['countries' => $this->countries()]);
38+
}
39+
40+
public function libraries()
41+
{
42+
return view('form.components.libraries', ['countries' => $this->countries()]);
43+
}
44+
45+
public function custom()
46+
{
47+
return view('form.components.custom', ['countries' => $this->countries()]);
48+
}
49+
50+
public function eloquent()
51+
{
52+
return view('form.components.eloquent', ['dummy' => Dummy::first()]);
53+
}
54+
55+
public function fluent()
56+
{
57+
return view('form.components.fluent', ['dummy' => new Fluent([
58+
'input' => 'input',
59+
'textarea' => 'textarea',
60+
'select' => 'b',
61+
'checkbox' => true,
62+
'radio' => 'b',
63+
'json' => ['nested' => ['array'], 'key' => 'key'],
64+
'secret' => 'secret',
65+
])]);
66+
}
67+
68+
public function unguarded()
69+
{
70+
return view('form.components.unguarded', ['dummy' => [
71+
'input' => 'input',
72+
'secret' => 'secret',
73+
]]);
74+
}
75+
76+
public function defaultUnguarded()
77+
{
78+
Form::defaultUnguarded();
79+
80+
return view('form.components.fluent', ['dummy' => [
81+
'input' => 'input',
82+
'secret' => 'secret',
83+
]]);
84+
}
85+
86+
public function submit(Request $request)
87+
{
88+
$request->validate([
89+
'name' => ['required', 'string'],
90+
'password' => ['required', 'string'],
91+
'secret' => ['required', 'string'],
92+
'file' => ['required', 'file'],
93+
'files' => ['required', 'array', 'min:2'],
94+
'files.*' => ['required', 'file'],
95+
'date' => ['required', 'string'],
96+
'time' => ['required', 'string'],
97+
'biography' => ['required', 'string'],
98+
'options' => ['required', 'array', 'min:1'],
99+
'language' => ['required', 'in:en,nl'],
100+
'country' => ['required', 'string', Rule::in(array_keys($this->countries()))],
101+
'terms' => ['required', 'boolean', 'accepted'],
102+
]);
103+
104+
return redirect()->route('navigation.one');
105+
}
106+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Models\Keyword;
6+
use App\Models\Tag;
7+
use App\Models\User;
8+
use Illuminate\Http\Request;
9+
10+
class FormRelationsController
11+
{
12+
public function belongsToMany()
13+
{
14+
return view('form.components.belongs-to-many', [
15+
'user' => User::first(),
16+
17+
'tagOptions' => Tag::get()->keyBy->id->map->name,
18+
]);
19+
}
20+
21+
public function storeBelongsToMany(Request $request)
22+
{
23+
$data = $request->validate([
24+
'tags' => ['required', 'array'],
25+
'tags.*' => ['required', 'exists:tags,id'],
26+
]);
27+
28+
User::first()->tags()->sync($data['tags']);
29+
30+
return redirect()->route('navigation.one');
31+
}
32+
33+
//
34+
35+
public function morphToMany()
36+
{
37+
return view('form.components.morph-to-many', [
38+
'user' => User::first(),
39+
40+
'keywordOptions' => Keyword::get()->keyBy->id->map->keyword,
41+
]);
42+
}
43+
44+
public function storeMorphToMany(Request $request)
45+
{
46+
$data = $request->validate([
47+
'keywords' => ['required', 'array'],
48+
'keywords.*' => ['required', 'exists:keywords,id'],
49+
]);
50+
51+
User::first()->keywords()->sync($data['keywords']);
52+
53+
return redirect()->route('navigation.one');
54+
}
55+
56+
public function twoForms()
57+
{
58+
return view('form.components.two-forms', [
59+
'firstUser' => User::skip(0)->first(),
60+
'secondUser' => User::skip(1)->first(),
61+
62+
'tagOptions' => Tag::get()->keyBy->id->map->name,
63+
]);
64+
}
65+
}

app/app/Models/Dummy.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
class Dummy extends Model
9+
{
10+
use HasFactory;
11+
12+
public $casts = [
13+
'checkbox' => 'boolean',
14+
'json' => 'json',
15+
];
16+
}

app/app/Models/Keyword.php

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
class Keyword extends Model
9+
{
10+
use HasFactory;
11+
}

app/app/Models/Tag.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
class Tag extends Model
9+
{
10+
use HasFactory;
11+
12+
public function users()
13+
{
14+
return $this->belongsToMany(User::class);
15+
}
16+
}

app/app/Models/User.php

+10
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,14 @@ class User extends Authenticatable
4040
protected $casts = [
4141
'email_verified_at' => 'datetime',
4242
];
43+
44+
public function tags()
45+
{
46+
return $this->belongsToMany(Tag::class);
47+
}
48+
49+
public function keywords()
50+
{
51+
return $this->morphToMany(Keyword::class, 'keywordable');
52+
}
4353
}

app/composer.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
"laravel/sanctum": "^2.14.1",
1616
"laravel/tinker": "^2.7",
1717
"pusher/pusher-php-server": "^7.0",
18-
"spatie/laravel-query-builder": "^5.0"
18+
"spatie/laravel-query-builder": "^5.0",
19+
"spatie/once": "^3.1"
1920
},
2021
"require-dev": {
22+
"barryvdh/laravel-debugbar": "^3.7",
2123
"fakerphp/faker": "^1.9.1",
2224
"laravel/dusk": "^6.25",
2325
"laravel/sail": "^1.0.1",
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Database\Factories;
4+
5+
use Illuminate\Database\Eloquent\Factories\Factory;
6+
7+
/**
8+
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Dummy>
9+
*/
10+
class DummyFactory extends Factory
11+
{
12+
/**
13+
* Define the model's default state.
14+
*
15+
* @return array<string, mixed>
16+
*/
17+
public function definition()
18+
{
19+
return [
20+
//
21+
];
22+
}
23+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Database\Factories;
4+
5+
use Illuminate\Database\Eloquent\Factories\Factory;
6+
7+
/**
8+
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Keyword>
9+
*/
10+
class KeywordFactory extends Factory
11+
{
12+
/**
13+
* Define the model's default state.
14+
*
15+
* @return array<string, mixed>
16+
*/
17+
public function definition()
18+
{
19+
return [
20+
'keyword' => $this->faker->word(),
21+
];
22+
}
23+
}

app/database/factories/TagFactory.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Database\Factories;
4+
5+
use Illuminate\Database\Eloquent\Factories\Factory;
6+
7+
/**
8+
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Tag>
9+
*/
10+
class TagFactory extends Factory
11+
{
12+
/**
13+
* Define the model's default state.
14+
*
15+
* @return array<string, mixed>
16+
*/
17+
public function definition()
18+
{
19+
return [
20+
'name' => $this->faker->word(),
21+
];
22+
}
23+
}

app/database/factories/UserFactory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public function definition()
1919
{
2020
return [
2121
'name' => fake()->name(),
22-
'email' => fake()->safeEmail(),
22+
'email' => Str::random(16) . fake()->safeEmail(),
2323
'email_verified_at' => now(),
2424
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
2525
'remember_token' => Str::random(10),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::create('tags', function (Blueprint $table) {
17+
$table->id();
18+
$table->string('name');
19+
$table->timestamps();
20+
});
21+
}
22+
23+
/**
24+
* Reverse the migrations.
25+
*
26+
* @return void
27+
*/
28+
public function down()
29+
{
30+
Schema::dropIfExists('tags');
31+
}
32+
};

0 commit comments

Comments
 (0)