V2, better design, more functionalities.
21
app/Http/Controllers/ContactController.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
|
class ContactController extends Controller
|
||||||
|
{
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'name' => 'required|max:255',
|
||||||
|
'message' => 'required|max:5000',
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return response()->json(['status' => 'success']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,7 +32,7 @@ class EducationController extends Controller
|
|||||||
$education = Education::create($data);
|
$education = Education::create($data);
|
||||||
|
|
||||||
if ($request->hasFile('afbeelding')) {
|
if ($request->hasFile('afbeelding')) {
|
||||||
$education->addMediaFromRequest('afbeelding')->toMediaCollection('afbeelding');
|
$education->addMediaFromRequest('afbeelding')->toMediaCollection('image');
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->route('educations.index')->with('success', 'Opleiding toegevoegd.');
|
return redirect()->route('educations.index')->with('success', 'Opleiding toegevoegd.');
|
||||||
@@ -62,8 +62,9 @@ class EducationController extends Controller
|
|||||||
$education->update($data);
|
$education->update($data);
|
||||||
|
|
||||||
if ($request->hasFile('afbeelding')) {
|
if ($request->hasFile('afbeelding')) {
|
||||||
$education->clearMediaCollection('afbeelding');
|
$education->clearMediaCollection('image');
|
||||||
$education->addMediaFromRequest('afbeelding')->toMediaCollection('afbeelding');
|
|
||||||
|
$education->addMediaFromRequest('afbeelding')->toMediaCollection('image');
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->route('educations.index')->with('success', 'Opleiding bijgewerkt.');
|
return redirect()->route('educations.index')->with('success', 'Opleiding bijgewerkt.');
|
||||||
|
|||||||
@@ -7,15 +7,55 @@ use App\Models\Personalia;
|
|||||||
use App\Models\Skill;
|
use App\Models\Skill;
|
||||||
use App\Models\WorkExperience;
|
use App\Models\WorkExperience;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use App\Jobs\NotifyTelegramAboutPersonaliaClick;
|
||||||
|
use App\Jobs\NotifyTelegramAboutContactMessage;
|
||||||
|
|
||||||
class FrontendController extends Controller
|
class FrontendController extends Controller
|
||||||
{
|
{
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$skills = Skill::all();
|
$skills = Skill::all()->groupBy('type');
|
||||||
|
|
||||||
$personalia = Personalia::all();
|
$personalia = Personalia::all();
|
||||||
$education = Education::all();
|
$education = Education::orderBy('startdatum', 'desc')->get();
|
||||||
$experience = WorkExperience::all();
|
$experience = WorkExperience::orderBy('startdatum', 'desc')->get();
|
||||||
|
|
||||||
return view('welcome', compact('skills', 'personalia', 'education', 'experience'));
|
return view('welcome', compact('skills', 'personalia', 'education', 'experience'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPersonalia($id)
|
||||||
|
{
|
||||||
|
$item = Personalia::findOrFail($id);
|
||||||
|
NotifyTelegramAboutPersonaliaClick::dispatch(
|
||||||
|
$item,
|
||||||
|
request()->ip(),
|
||||||
|
request()->userAgent()
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'value' => $item->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function message(Request $request)
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'name' => 'required|string|max:255',
|
||||||
|
'message' => 'required|string|max:5000',
|
||||||
|
'email' => 'nullable|email|max:255',
|
||||||
|
'phone' => 'nullable|string|max:50',
|
||||||
|
]);
|
||||||
|
|
||||||
|
NotifyTelegramAboutContactMessage::dispatch(
|
||||||
|
$validated['name'],
|
||||||
|
$validated['message'],
|
||||||
|
$request->ip(),
|
||||||
|
$request->userAgent(),
|
||||||
|
$validated['email'] ?? null,
|
||||||
|
$validated['phone'] ?? null
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json(['status' => 'success']);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,14 @@ class SkillController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
|
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'title' => 'required|string|max:255',
|
'title' => 'required|string|max:255',
|
||||||
'description' => 'nullable|string',
|
'description' => 'nullable|string',
|
||||||
'rating' => 'required|integer|min:1|max:10',
|
'rating' => 'required|numeric|min:1|max:10',
|
||||||
'image' => 'nullable|image|max:2048',
|
'image' => 'nullable|image|max:2048',
|
||||||
|
'type' => 'required|in:rating,tag,other',
|
||||||
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$skill = Skill::create($validated);
|
$skill = Skill::create($validated);
|
||||||
@@ -69,8 +72,10 @@ class SkillController extends Controller
|
|||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'title' => 'required|string|max:255',
|
'title' => 'required|string|max:255',
|
||||||
'description' => 'nullable|string',
|
'description' => 'nullable|string',
|
||||||
'rating' => 'required|integer|min:1|max:10',
|
'rating' => 'required|numeric|min:1|max:10',
|
||||||
'image' => 'nullable|image|max:2048',
|
'image' => 'nullable|image|max:2048',
|
||||||
|
'type' => 'required|in:rating,tag,other',
|
||||||
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$skill->update($validated);
|
$skill->update($validated);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class WorkExperienceController extends Controller
|
|||||||
$experience = WorkExperience::create($data);
|
$experience = WorkExperience::create($data);
|
||||||
|
|
||||||
if ($request->hasFile('afbeelding')) {
|
if ($request->hasFile('afbeelding')) {
|
||||||
$experience->addMediaFromRequest('afbeelding')->toMediaCollection('afbeelding');
|
$experience->addMediaFromRequest('afbeelding')->toMediaCollection('image');
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->route('work-experiences.index')->with('success', 'Ervaring toegevoegd.');
|
return redirect()->route('work-experiences.index')->with('success', 'Ervaring toegevoegd.');
|
||||||
@@ -58,11 +58,13 @@ class WorkExperienceController extends Controller
|
|||||||
'afbeelding' => 'nullable|image|max:2048',
|
'afbeelding' => 'nullable|image|max:2048',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$workExperience->update($data);
|
$workExperience->update($data);
|
||||||
|
|
||||||
if ($request->hasFile('afbeelding')) {
|
if ($request->hasFile('afbeelding')) {
|
||||||
$workExperience->clearMediaCollection('afbeelding');
|
$workExperience->clearMediaCollection('image');
|
||||||
$workExperience->addMediaFromRequest('afbeelding')->toMediaCollection('afbeelding');
|
$workExperience->addMediaFromRequest('afbeelding')->toMediaCollection('image');
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->route('work-experiences.index')->with('success', 'Ervaring bijgewerkt.');
|
return redirect()->route('work-experiences.index')->with('success', 'Ervaring bijgewerkt.');
|
||||||
|
|||||||
60
app/Jobs/NotifyTelegramAboutContactMessage.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
|
||||||
|
class NotifyTelegramAboutContactMessage implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
protected string $name;
|
||||||
|
protected string $message;
|
||||||
|
protected string $ip;
|
||||||
|
protected string $userAgent;
|
||||||
|
protected string $email;
|
||||||
|
protected string $phone;
|
||||||
|
|
||||||
|
public function __construct(string $name, string $message, string $ip, string $userAgent, ?string $email = null, ?string $phone = null)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->message = $message;
|
||||||
|
$this->ip = $ip;
|
||||||
|
$this->userAgent = $userAgent;
|
||||||
|
$this->email = $email;
|
||||||
|
$this->phone = $phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$email = $this->email ?? '–';
|
||||||
|
$phone = $this->phone ?? '–';
|
||||||
|
|
||||||
|
$text = <<<TEXT
|
||||||
|
📩 *Nieuw contactbericht ontvangen*
|
||||||
|
|
||||||
|
👤 Naam: *{$this->name}*
|
||||||
|
|
||||||
|
💬 Bericht:
|
||||||
|
{$this->message}
|
||||||
|
📧 Email: {$email}
|
||||||
|
📱 Telefoon: {$phone}
|
||||||
|
🌐 IP: {$this->ip}
|
||||||
|
🧭 User Agent: `{$this->userAgent}`
|
||||||
|
|
||||||
|
🕒 Tijdstip: *{now()->format('d-m-Y H:i')}*
|
||||||
|
TEXT;
|
||||||
|
|
||||||
|
Http::post("https://api.telegram.org/bot" . config('services.telegram.bot_token') . "/sendMessage", [
|
||||||
|
'chat_id' => config('services.telegram.chat_id'),
|
||||||
|
'text' => $text,
|
||||||
|
'parse_mode' => 'Markdown',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
app/Jobs/NotifyTelegramAboutPersonaliaClick.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Personalia;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
|
||||||
|
class NotifyTelegramAboutPersonaliaClick implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
protected $personalia;
|
||||||
|
protected $ip;
|
||||||
|
protected $userAgent;
|
||||||
|
|
||||||
|
public function __construct(Personalia $personalia, $ip, $userAgent)
|
||||||
|
{
|
||||||
|
$this->personalia = $personalia;
|
||||||
|
$this->ip = $ip;
|
||||||
|
$this->userAgent = $userAgent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$message = <<<TEXT
|
||||||
|
👤 *Persoonlijke gegevens bekeken*
|
||||||
|
|
||||||
|
Naam: {$this->personalia->value}
|
||||||
|
IP: {$this->ip}
|
||||||
|
User Agent: `{$this->userAgent}`
|
||||||
|
|
||||||
|
📅 Tijdstip: *{$this->personalia->updated_at->format('d-m-Y H:i')}*
|
||||||
|
TEXT;
|
||||||
|
|
||||||
|
Http::post("https://api.telegram.org/bot" . config('services.telegram.bot_token') . "/sendMessage", [
|
||||||
|
'chat_id' => config('services.telegram.chat_id'),
|
||||||
|
'text' => $message,
|
||||||
|
'parse_mode' => 'Markdown',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,4 +16,13 @@ class Education extends Model implements HasMedia
|
|||||||
'einddatum',
|
'einddatum',
|
||||||
'beschrijving',
|
'beschrijving',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function image()
|
||||||
|
{
|
||||||
|
return $this->getFirstMedia('image');
|
||||||
|
}
|
||||||
|
public function imageUrl()
|
||||||
|
{
|
||||||
|
return $this->image() ? $this->image()->getUrl() : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,4 +10,13 @@ class Personalia extends Model
|
|||||||
protected $casts = [
|
protected $casts = [
|
||||||
'hidden' => 'boolean',
|
'hidden' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function image()
|
||||||
|
{
|
||||||
|
return $this->getFirstMedia('image');
|
||||||
|
}
|
||||||
|
public function imageUrl()
|
||||||
|
{
|
||||||
|
return $this->image() ? $this->image()->getUrl() : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,14 @@ class Skill extends Model implements HasMedia
|
|||||||
{
|
{
|
||||||
use InteractsWithMedia;
|
use InteractsWithMedia;
|
||||||
|
|
||||||
protected $fillable = ['title', 'description', 'rating'];
|
protected $fillable = ['title', 'description', 'rating', 'type'];
|
||||||
|
|
||||||
|
public function image()
|
||||||
|
{
|
||||||
|
return $this->getFirstMedia('image');
|
||||||
|
}
|
||||||
|
public function imageUrl()
|
||||||
|
{
|
||||||
|
return $this->image() ? $this->image()->getUrl() : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,5 +18,14 @@ class WorkExperience extends Model implements HasMedia
|
|||||||
'beschrijving',
|
'beschrijving',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function image()
|
||||||
|
{
|
||||||
|
return $this->getFirstMedia('image');
|
||||||
|
}
|
||||||
|
public function imageUrl()
|
||||||
|
{
|
||||||
|
return $this->image() ? $this->image()->getUrl() : null;
|
||||||
|
}
|
||||||
|
|
||||||
// Als je mediaconversies of image handling wil: hier kun je die later toevoegen
|
// Als je mediaconversies of image handling wil: hier kun je die later toevoegen
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,5 +34,9 @@ return [
|
|||||||
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
|
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'telegram' => [
|
||||||
|
'bot_token' => env('TELEGRAM_BOT_TOKEN'),
|
||||||
|
'chat_id' => env('TELEGRAM_CHAT_ID'),
|
||||||
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|||||||
32
database/data/education.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"opleiding": "Havo",
|
||||||
|
"instituut": "Blaise pascal (Scala rietvelden)",
|
||||||
|
"startdatum": "2006-07-01",
|
||||||
|
"einddatum": "2013-01-07",
|
||||||
|
"beschrijving": "Mijn middelbare schoolperiode kende een hobbelig begin: ik startte op het havo/vwo, maar had in de eerste jaren moeite met motivatie en discipline. Daardoor ben ik afgezakt naar het mavo-niveau. Op de mavo heb ik mezelf herpakt en mijn focus hervonden. Dankzij die ommekeer kon ik succesvol doorstromen naar de havo, waar ik mijn diploma met ruime voldoendes heb behaald. Deze periode heeft mij geleerd hoe belangrijk eigen inzet en doelgerichtheid zijn.",
|
||||||
|
"created_at": "2025-06-18 23:08:02",
|
||||||
|
"updated_at": "2025-06-18 23:20:19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"opleiding": "Internation Business and Management Studies",
|
||||||
|
"instituut": "Hogeschool Rotterdam",
|
||||||
|
"startdatum": "2013-07-01",
|
||||||
|
"einddatum": "2014-07-01",
|
||||||
|
"beschrijving": "International Business and Management Studies is een brede economische hbo-opleiding gericht op internationale handel, marketing en bedrijfsvoering. Tijdens het eerste jaar maakte ik kennis met onderwerpen als exportstrategieën, interculturele communicatie en organisatiekunde. Hoewel ik waardevolle inzichten heb opgedaan, merkte ik al snel dat de inhoud en aanpak van de opleiding niet goed aansloten bij mij.",
|
||||||
|
"created_at": "2025-06-18 23:11:45",
|
||||||
|
"updated_at": "2025-06-18 23:11:45"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"opleiding": "HBO Business Studies (Specialisering logistiek)",
|
||||||
|
"instituut": "Inholland Rotterdam",
|
||||||
|
"startdatum": "2014-07-01",
|
||||||
|
"einddatum": "2017-07-01",
|
||||||
|
"beschrijving": "Tijdens deze hbo-opleiding verdiepte ik mij in bedrijfskunde, ondernemerschap en supply chain management. In de laatste fase volgde ik de specialisatie Logistiek aan de vestiging in Haarlem, met een sterke focus op luchtvaartlogistiek en internationale goederenstromen. Hoewel ik brede kennis heb opgedaan binnen het vakgebied, heb ik de opleiding uiteindelijk voortijdig moeten beëindigen. In 2016 startte ik mijn eigen bedrijf, dat in korte tijd sterk groeide. Het combineren van een fulltime afstudeerstage met mijn ondernemersverantwoordelijkheden bleek op dat moment niet haalbaar.",
|
||||||
|
"created_at": "2025-06-18 23:17:49",
|
||||||
|
"updated_at": "2025-06-18 23:17:49"
|
||||||
|
}
|
||||||
|
]
|
||||||
762
database/data/media.json
Normal file
@@ -0,0 +1,762 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"model_type": "App\\Models\\WorkExperience",
|
||||||
|
"model_id": "1",
|
||||||
|
"uuid": "3aa34696-9a24-4efe-a255-71fb23093bdb",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "jumbo",
|
||||||
|
"file_name": "jumbo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "3828",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 17:58:25",
|
||||||
|
"updated_at": "2025-07-08 17:58:25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "1",
|
||||||
|
"uuid": "913531cd-8948-45a6-9f8e-abdcfed30677",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "php-logo",
|
||||||
|
"file_name": "php-logo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "80608",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:22:47",
|
||||||
|
"updated_at": "2025-07-08 19:22:47"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"model_type": "App\\Models\\WorkExperience",
|
||||||
|
"model_id": "2",
|
||||||
|
"uuid": "da630aba-72a4-4dbe-8deb-95d994adde75",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "sitiweb-logo",
|
||||||
|
"file_name": "sitiweb-logo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "2296",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 18:22:18",
|
||||||
|
"updated_at": "2025-07-08 18:22:18"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "3",
|
||||||
|
"uuid": "486f344f-dd27-4636-904a-4a5686a06d42",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "5848152fcef1014c0b5e4967",
|
||||||
|
"file_name": "5848152fcef1014c0b5e4967.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "9955",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:25:31",
|
||||||
|
"updated_at": "2025-07-08 19:25:31"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "2",
|
||||||
|
"uuid": "73a14a0b-4f75-41c4-933b-63c107492162",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "JavaScript",
|
||||||
|
"file_name": "JavaScript.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "5418",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:35:02",
|
||||||
|
"updated_at": "2025-07-08 19:35:02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6",
|
||||||
|
"model_type": "App\\Models\\Education",
|
||||||
|
"model_id": "1",
|
||||||
|
"uuid": "b8166354-3e19-4eb5-8778-5f160c5528c0",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "images",
|
||||||
|
"file_name": "images.jpg",
|
||||||
|
"mime_type": "image/jpeg",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "10052",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 18:01:03",
|
||||||
|
"updated_at": "2025-07-08 18:01:03"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7",
|
||||||
|
"model_type": "App\\Models\\WorkExperience",
|
||||||
|
"model_id": "3",
|
||||||
|
"uuid": "8b814d2e-15f3-4f73-b6b4-ff5114346f63",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "internettoday-logo",
|
||||||
|
"file_name": "internettoday-logo.jpg",
|
||||||
|
"mime_type": "image/jpeg",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "13085",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 18:29:44",
|
||||||
|
"updated_at": "2025-07-08 18:29:44"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8",
|
||||||
|
"model_type": "App\\Models\\Education",
|
||||||
|
"model_id": "2",
|
||||||
|
"uuid": "0af4f477-13a0-4926-988f-44cfd886b88e",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "hr",
|
||||||
|
"file_name": "hr.jpg",
|
||||||
|
"mime_type": "image/jpeg",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "4159",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 18:00:56",
|
||||||
|
"updated_at": "2025-07-08 18:00:56"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "4",
|
||||||
|
"uuid": "f3d64062-0571-40db-8871-18584a45420e",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "linux-logo",
|
||||||
|
"file_name": "linux-logo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "145726",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:26:24",
|
||||||
|
"updated_at": "2025-07-08 19:26:24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "10",
|
||||||
|
"model_type": "App\\Models\\Education",
|
||||||
|
"model_id": "3",
|
||||||
|
"uuid": "3d811274-5a83-4b56-99af-d87a9d404fc5",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "inh",
|
||||||
|
"file_name": "inh.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "3053",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 18:00:48",
|
||||||
|
"updated_at": "2025-07-08 18:00:48"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "11",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "5",
|
||||||
|
"uuid": "58b96151-814b-4b83-a775-f64101f046a9",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "git-logo",
|
||||||
|
"file_name": "git-logo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "2383",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 17:12:48",
|
||||||
|
"updated_at": "2025-07-08 17:12:48"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "12",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "7",
|
||||||
|
"uuid": "05cd0535-e055-434d-b025-c9c855651dd3",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "lara",
|
||||||
|
"file_name": "lara.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "37110",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:21:24",
|
||||||
|
"updated_at": "2025-07-08 19:21:24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "13",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "8",
|
||||||
|
"uuid": "65d02709-dc31-4ccf-84da-7e0ac58c62bc",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Livewire-logo",
|
||||||
|
"file_name": "Livewire-logo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "32291",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:27:21",
|
||||||
|
"updated_at": "2025-07-08 19:27:21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "14",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "9",
|
||||||
|
"uuid": "7e04527d-91c8-4017-9f58-31f9b209e5a8",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Tailwind CSS",
|
||||||
|
"file_name": "Tailwind-CSS.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "6255",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:29:55",
|
||||||
|
"updated_at": "2025-07-08 19:29:55"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "15",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "10",
|
||||||
|
"uuid": "428f92d1-918a-4490-a2ac-ec613c71b073",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Postman",
|
||||||
|
"file_name": "Postman.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "8252",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:34:47",
|
||||||
|
"updated_at": "2025-07-08 19:34:47"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "16",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "11",
|
||||||
|
"uuid": "a2ff85d9-e3e6-4e12-ad9d-66b632bd187d",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Docker",
|
||||||
|
"file_name": "Docker.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "11082",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:34:31",
|
||||||
|
"updated_at": "2025-07-08 19:34:31"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "17",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "12",
|
||||||
|
"uuid": "7b827656-bef3-44eb-bb70-53e4b77b9148",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "proxmox-logo",
|
||||||
|
"file_name": "proxmox-logo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "20014",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:33:25",
|
||||||
|
"updated_at": "2025-07-08 19:33:25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "18",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "13",
|
||||||
|
"uuid": "12ce5e7b-fc63-4657-a2ff-edef35d4bb78",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Grafana",
|
||||||
|
"file_name": "Grafana.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "12920",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:34:14",
|
||||||
|
"updated_at": "2025-07-08 19:34:14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "19",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "14",
|
||||||
|
"uuid": "496ad2ef-7df9-42b8-b7ed-6e4424621b77",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Cloudflare",
|
||||||
|
"file_name": "Cloudflare.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "7363",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:35:34",
|
||||||
|
"updated_at": "2025-07-08 19:35:34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "20",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "15",
|
||||||
|
"uuid": "019cc0f2-57b9-4e94-b307-ecb69988ed00",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "directadmnin-logo",
|
||||||
|
"file_name": "directadmnin-logo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "2364",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:37:04",
|
||||||
|
"updated_at": "2025-07-08 19:37:04"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "21",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "16",
|
||||||
|
"uuid": "197de2dd-42cb-469e-bd5d-b9d2692ddede",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "MySQL",
|
||||||
|
"file_name": "MySQL.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "9330",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:37:57",
|
||||||
|
"updated_at": "2025-07-08 19:37:57"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "22",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "17",
|
||||||
|
"uuid": "c5fed034-9745-4fc3-84c0-720372e6ea56",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Uptime-Kuma-Logo",
|
||||||
|
"file_name": "Uptime-Kuma-Logo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "36536",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:38:36",
|
||||||
|
"updated_at": "2025-07-08 19:38:36"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "23",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "18",
|
||||||
|
"uuid": "2e362926-027a-4e8a-93bd-9a27e9e0fc18",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "NGINX",
|
||||||
|
"file_name": "NGINX.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "5301",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:39:19",
|
||||||
|
"updated_at": "2025-07-08 19:39:19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "24",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "19",
|
||||||
|
"uuid": "22a353cd-410a-484f-8362-09a00d97a183",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Visual Studio Code (VS Code)",
|
||||||
|
"file_name": "Visual-Studio-Code-(VS-Code).png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "16772",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:40:32",
|
||||||
|
"updated_at": "2025-07-08 19:40:32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "25",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "20",
|
||||||
|
"uuid": "d1e09302-0730-493f-9b35-a6f82b27e7b6",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "GIMP",
|
||||||
|
"file_name": "GIMP.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "32519",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:41:59",
|
||||||
|
"updated_at": "2025-07-08 19:41:59"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "26",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "21",
|
||||||
|
"uuid": "1d7d73e4-f373-485a-9205-7261869de4b0",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "WordPress",
|
||||||
|
"file_name": "WordPress.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "21613",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:42:37",
|
||||||
|
"updated_at": "2025-07-08 19:42:37"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "27",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "22",
|
||||||
|
"uuid": "9e062f71-7e0b-4bb0-b455-c4b954a607a8",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "WooCommerce",
|
||||||
|
"file_name": "WooCommerce.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "8433",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:43:00",
|
||||||
|
"updated_at": "2025-07-08 19:43:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "28",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "23",
|
||||||
|
"uuid": "dda5797d-16c3-4a70-bf4d-e3eded1d1003",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Vaultwarden--Streamline-Simple-Icons",
|
||||||
|
"file_name": "Vaultwarden--Streamline-Simple-Icons.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "7139",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:44:30",
|
||||||
|
"updated_at": "2025-07-08 19:44:30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "29",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "24",
|
||||||
|
"uuid": "c981f25b-b486-4b1d-a4f3-5a15d85464ac",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "healthchecks.logo",
|
||||||
|
"file_name": "healthchecks.logo.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "11561",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:45:12",
|
||||||
|
"updated_at": "2025-07-08 19:45:12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "30",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "25",
|
||||||
|
"uuid": "606ecdbf-9ed5-4853-b8eb-405bc35a120d",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "GitLab",
|
||||||
|
"file_name": "GitLab.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "24046",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:46:14",
|
||||||
|
"updated_at": "2025-07-08 19:46:14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "31",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "26",
|
||||||
|
"uuid": "3be7bb80-74a6-444d-b2ef-b072900fc03d",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "GitHub",
|
||||||
|
"file_name": "GitHub.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "8449",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:46:27",
|
||||||
|
"updated_at": "2025-07-08 19:46:27"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "32",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "27",
|
||||||
|
"uuid": "939e8d71-73c4-41ea-ae35-6132cecfdc3c",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Fedora",
|
||||||
|
"file_name": "Fedora.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "10591",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:46:54",
|
||||||
|
"updated_at": "2025-07-08 19:46:54"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "33",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "28",
|
||||||
|
"uuid": "671081cf-b852-41ff-a746-835f75beaa46",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Ubuntu",
|
||||||
|
"file_name": "Ubuntu.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "11230",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:47:15",
|
||||||
|
"updated_at": "2025-07-08 19:47:15"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "34",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "29",
|
||||||
|
"uuid": "0c968a1c-202c-4635-b613-04874733d994",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "CentOS",
|
||||||
|
"file_name": "CentOS.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "11745",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:47:43",
|
||||||
|
"updated_at": "2025-07-08 19:47:43"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "35",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "30",
|
||||||
|
"uuid": "1e78c7c9-d73f-4ea8-9426-b274d2b63279",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Debian",
|
||||||
|
"file_name": "Debian.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "6999",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:48:14",
|
||||||
|
"updated_at": "2025-07-08 19:48:14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "36",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "31",
|
||||||
|
"uuid": "b36a3c4f-d19e-4832-b0b9-9728ce850f45",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "Composer",
|
||||||
|
"file_name": "Composer.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "31190",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:48:40",
|
||||||
|
"updated_at": "2025-07-08 19:48:40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "37",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "32",
|
||||||
|
"uuid": "6a888cd6-982b-4e1a-87c8-fd2a200f8fc5",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "NPM",
|
||||||
|
"file_name": "NPM.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "1136",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:49:09",
|
||||||
|
"updated_at": "2025-07-08 19:49:09"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "38",
|
||||||
|
"model_type": "App\\Models\\Skill",
|
||||||
|
"model_id": "33",
|
||||||
|
"uuid": "fb6f3d4d-9a4b-4c4a-87a9-09b9c9bb58c9",
|
||||||
|
"collection_name": "image",
|
||||||
|
"name": "HTML5",
|
||||||
|
"file_name": "HTML5.png",
|
||||||
|
"mime_type": "image/png",
|
||||||
|
"disk": "public",
|
||||||
|
"conversions_disk": "public",
|
||||||
|
"size": "31694",
|
||||||
|
"manipulations": [],
|
||||||
|
"custom_properties": [],
|
||||||
|
"generated_conversions": [],
|
||||||
|
"responsive_images": [],
|
||||||
|
"order_column": 1,
|
||||||
|
"created_at": "2025-07-08 19:50:02",
|
||||||
|
"updated_at": "2025-07-08 19:50:02"
|
||||||
|
}
|
||||||
|
]
|
||||||
29
database/data/personalia.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"key": "Email",
|
||||||
|
"value": "roberto@guagliardo.nl",
|
||||||
|
"hidden": 1,
|
||||||
|
"icon": "fa-solid fa-envelope",
|
||||||
|
"created_at": "2025-06-18 20:24:49",
|
||||||
|
"updated_at": "2025-07-08 18:47:19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"key": "Telefoonnummer",
|
||||||
|
"value": "+ 31 6 444 60 893",
|
||||||
|
"hidden": 1,
|
||||||
|
"icon": "fa-solid fa-phone",
|
||||||
|
"created_at": "2025-06-18 22:43:12",
|
||||||
|
"updated_at": "2025-06-18 22:43:12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"key": "Adres",
|
||||||
|
"value": "Hoefsmid 16<br>3201TC Spijkenisse",
|
||||||
|
"hidden": 1,
|
||||||
|
"icon": "fa-solid fa-home",
|
||||||
|
"created_at": "2025-06-18 22:50:09",
|
||||||
|
"updated_at": "2025-06-18 22:50:09"
|
||||||
|
}
|
||||||
|
]
|
||||||
353
database/data/skills.json
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"type": "rating",
|
||||||
|
"title": "PHP",
|
||||||
|
"description": "Met meer dan 9 jaar ervaring in PHP, WordPress en Laravel, heb ik brede expertise opgebouwd in het ontwikkelen van zowel maatwerkfuncties als complete webapplicaties.",
|
||||||
|
"rating": 9,
|
||||||
|
"created_at": "2025-07-08 16:49:03",
|
||||||
|
"updated_at": "2025-07-08 17:14:02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"type": "rating",
|
||||||
|
"title": "JavaScript",
|
||||||
|
"description": "Brede ervaring met JavaScript, van vanilla JS tot moderne frameworks zoals React – inzetbaar voor zowel interactieve interfaces als volledige front-end architecturen.",
|
||||||
|
"rating": 7,
|
||||||
|
"created_at": "2025-07-08 16:54:03",
|
||||||
|
"updated_at": "2025-07-08 16:54:03"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4",
|
||||||
|
"type": "rating",
|
||||||
|
"title": "Python",
|
||||||
|
"description": "Ruime ervaring met Python voor het bouwen van tools en automatiseringen: van beeldherkenning en muisbesturing tot webscrapers, image-optimalisatie en importtools voor webshops.",
|
||||||
|
"rating": 7,
|
||||||
|
"created_at": "2025-07-08 17:00:01",
|
||||||
|
"updated_at": "2025-07-08 17:00:01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5",
|
||||||
|
"type": "rating",
|
||||||
|
"title": "Linux & Serverbeheer",
|
||||||
|
"description": "Ervaren in het opzetten, beheren en automatiseren van Linux-omgevingen. Dagelijks gebruik van Fedora (werkstation), en zakelijk gewerkt met CentOS, AlmaLinux en Debian. Bekwaam in Bash-scripting, serveronderhoud, optimalisatie en het draaien van hostingplatformen.",
|
||||||
|
"rating": 8,
|
||||||
|
"created_at": "2025-07-08 17:02:21",
|
||||||
|
"updated_at": "2025-07-08 20:11:47"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7",
|
||||||
|
"type": "rating",
|
||||||
|
"title": "DevOps & Tools",
|
||||||
|
"description": "Ervaring met Git, Docker, Nginx, SSH en cronjobs. Bekend met CI/CD-principes en inzet van tooling voor automatisering en monitoring binnen ontwikkel- en hostingomgevingen.",
|
||||||
|
"rating": 8,
|
||||||
|
"created_at": "2025-07-08 17:12:48",
|
||||||
|
"updated_at": "2025-07-08 17:12:48"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9",
|
||||||
|
"type": "tag",
|
||||||
|
"title": "Leergierig",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:08:00",
|
||||||
|
"updated_at": "2025-07-08 19:08:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "10",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Laravel",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:19:00",
|
||||||
|
"updated_at": "2025-07-08 19:19:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "11",
|
||||||
|
"type": "other",
|
||||||
|
"title": "LiveWire",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:27:21",
|
||||||
|
"updated_at": "2025-07-08 19:27:21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "12",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Tailwind",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:29:55",
|
||||||
|
"updated_at": "2025-07-08 19:29:55"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "13",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Postman",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:32:42",
|
||||||
|
"updated_at": "2025-07-08 19:32:42"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "14",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Docker",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:32:55",
|
||||||
|
"updated_at": "2025-07-08 19:32:55"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "15",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Proxmox",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:33:25",
|
||||||
|
"updated_at": "2025-07-08 19:33:25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "16",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Grafana",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:34:14",
|
||||||
|
"updated_at": "2025-07-08 19:34:14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "17",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Cloudflare",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:35:34",
|
||||||
|
"updated_at": "2025-07-08 19:35:34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "18",
|
||||||
|
"type": "other",
|
||||||
|
"title": "directadmin",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:37:04",
|
||||||
|
"updated_at": "2025-07-08 19:37:04"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "19",
|
||||||
|
"type": "other",
|
||||||
|
"title": "MySQL/MariaDB",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:37:57",
|
||||||
|
"updated_at": "2025-07-08 19:37:57"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "20",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Uptime Kuma",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:38:36",
|
||||||
|
"updated_at": "2025-07-08 19:38:36"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "21",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Nginx",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:39:19",
|
||||||
|
"updated_at": "2025-07-08 19:39:19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "22",
|
||||||
|
"type": "other",
|
||||||
|
"title": "VS code",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:40:32",
|
||||||
|
"updated_at": "2025-07-08 19:40:32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "23",
|
||||||
|
"type": "other",
|
||||||
|
"title": "GIMP",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:41:59",
|
||||||
|
"updated_at": "2025-07-08 19:41:59"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "24",
|
||||||
|
"type": "other",
|
||||||
|
"title": "WordPress",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:42:37",
|
||||||
|
"updated_at": "2025-07-08 19:42:37"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "25",
|
||||||
|
"type": "other",
|
||||||
|
"title": "WooCommerce",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:43:00",
|
||||||
|
"updated_at": "2025-07-08 19:43:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "26",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Vaultwarden",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:44:30",
|
||||||
|
"updated_at": "2025-07-08 19:44:30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "27",
|
||||||
|
"type": "other",
|
||||||
|
"title": "HealthChecks",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:45:12",
|
||||||
|
"updated_at": "2025-07-08 19:45:12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "28",
|
||||||
|
"type": "other",
|
||||||
|
"title": "GitLab",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:46:14",
|
||||||
|
"updated_at": "2025-07-08 19:46:14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "29",
|
||||||
|
"type": "other",
|
||||||
|
"title": "GitHub",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:46:27",
|
||||||
|
"updated_at": "2025-07-08 19:46:27"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "30",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Fedora",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:46:54",
|
||||||
|
"updated_at": "2025-07-08 19:46:54"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "31",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Ubuntu",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:47:15",
|
||||||
|
"updated_at": "2025-07-08 19:47:15"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "32",
|
||||||
|
"type": "other",
|
||||||
|
"title": "CentOS",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:47:43",
|
||||||
|
"updated_at": "2025-07-08 19:47:51"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "33",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Debian",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:48:14",
|
||||||
|
"updated_at": "2025-07-08 19:48:14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "34",
|
||||||
|
"type": "other",
|
||||||
|
"title": "Composer",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:48:40",
|
||||||
|
"updated_at": "2025-07-08 19:48:40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "35",
|
||||||
|
"type": "other",
|
||||||
|
"title": "NPM",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:49:09",
|
||||||
|
"updated_at": "2025-07-08 19:49:09"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "36",
|
||||||
|
"type": "other",
|
||||||
|
"title": "HTML",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:50:02",
|
||||||
|
"updated_at": "2025-07-08 19:50:02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "37",
|
||||||
|
"type": "tag",
|
||||||
|
"title": "Klantgericht",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:50:46",
|
||||||
|
"updated_at": "2025-07-08 19:50:46"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "38",
|
||||||
|
"type": "tag",
|
||||||
|
"title": "Dekend aan oplossingen",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:51:09",
|
||||||
|
"updated_at": "2025-07-08 19:51:09"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "39",
|
||||||
|
"type": "tag",
|
||||||
|
"title": "Meedenkend",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:51:37",
|
||||||
|
"updated_at": "2025-07-08 19:51:37"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "40",
|
||||||
|
"type": "tag",
|
||||||
|
"title": "Probleemoplossend",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:52:22",
|
||||||
|
"updated_at": "2025-07-08 19:52:22"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "41",
|
||||||
|
"type": "tag",
|
||||||
|
"title": "Initiatiefrijk",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:52:45",
|
||||||
|
"updated_at": "2025-07-08 19:52:45"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "42",
|
||||||
|
"type": "tag",
|
||||||
|
"title": "Systeemdenker",
|
||||||
|
"description": null,
|
||||||
|
"rating": 5,
|
||||||
|
"created_at": "2025-07-08 19:53:28",
|
||||||
|
"updated_at": "2025-07-08 19:53:28"
|
||||||
|
}
|
||||||
|
]
|
||||||
32
database/data/work_experiences.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"werkgever": "Jumbo Supermarkten",
|
||||||
|
"functie": "Teamleider",
|
||||||
|
"startdatum": "2010-01-01",
|
||||||
|
"einddatum": "2018-12-31",
|
||||||
|
"beschrijving": "Na mijn start als bijbaanmedewerker ben ik binnen een jaar doorgegroeid naar de rol van teamleider. In deze functie werd ik door de regiomanager actief ingezet op verschillende filialen met een extra behoefte aan structuur, klantgerichtheid en kwaliteitsverbetering. Dit betrof zowel nieuwe vestigingen als filialen waar de bestaande werkmentaliteit niet strookte met de kwaliteitsnormen van Jumbo.\r\n\r\nMijn aanpak was altijd gericht op het verhogen van klanttevredenheid, het verbeteren van interne processen en het motiveren van collega’s. Dankzij mijn inzet en flexibiliteit heb ik meerdere filialen kunnen ondersteunen in het opzetten of herstructureren van een sterk, klantgericht team.",
|
||||||
|
"created_at": "2025-06-18 18:13:10",
|
||||||
|
"updated_at": "2025-06-18 18:13:10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"werkgever": "SitiWeb",
|
||||||
|
"functie": "Eigenaar / Technisch Specialist",
|
||||||
|
"startdatum": "2016-08-01",
|
||||||
|
"einddatum": "2024-10-01",
|
||||||
|
"beschrijving": "Als oprichter en eigenaar van Sitiweb heb ik gedurende acht jaar totaaloplossingen geleverd aan ondernemers met websites en webshops. De focus lag op zowel het verbeteren van websites als het technisch optimaliseren van hostingomgevingen.\r\n\r\nIk was verantwoordelijk voor de technische infrastructuur, het opzetten en beheren van hostingomgevingen (inclusief VPS-servers), en het uitvoeren van maatwerkoptimalisaties. Daarnaast adviseerde ik klanten actief over verbeteringen op het gebied van snelheid, veiligheid en gebruikservaring.\r\n\r\nOnder mijn leiding groeide Sitiweb uit tot een gewaardeerde partij binnen het MKB, met een sterke focus op kwaliteit en persoonlijke service. In 2024 heb ik besloten om een stap terug te doen, omdat het bedrijf dusdanig was gegroeid dat het met een klein team niet langer optimaal beheersbaar was.",
|
||||||
|
"created_at": "2025-07-08 18:22:12",
|
||||||
|
"updated_at": "2025-07-08 18:22:12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"werkgever": "InternetToday",
|
||||||
|
"functie": "Senior Developer",
|
||||||
|
"startdatum": "2024-10-01",
|
||||||
|
"einddatum": null,
|
||||||
|
"beschrijving": "Binnen InternetToday vervul ik een sleutelrol als senior developer met een brede technische verantwoordelijkheid. Ik heb de werkstructuur binnen het ontwikkelteam geoptimaliseerd door het opzetten van uitgebreide monitoring- en analysetools, wat direct heeft bijgedragen aan een efficiëntere en kwalitatievere werkwijze binnen het team.\r\n\r\nDaarnaast fungeer ik als brug tussen de developmentafdeling en de serverbeheerafdeling. Dankzij mijn diepgaande kennis van Linux, hosting en infrastructuur ben ik in staat om complexe technische vraagstukken snel op te lossen en oplossingen te ontwikkelen die doorgaans buiten de scope van het developmentteam vallen. Deze veelzijdigheid maakt mij een waardevolle schakel binnen het bedrijf.",
|
||||||
|
"created_at": "2025-07-08 18:29:36",
|
||||||
|
"updated_at": "2025-07-08 18:31:59"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('skills', function (Blueprint $table) {
|
||||||
|
$table->string('type')->default('rating')->after('id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('skills', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('type');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
38
database/seeders/EducationSeeder.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
|
class EducationSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$path = database_path('data/education.json');
|
||||||
|
|
||||||
|
if (!File::exists($path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verwijder alle bestaande records
|
||||||
|
DB::table('education')->truncate();
|
||||||
|
|
||||||
|
// Laad nieuwe data in
|
||||||
|
$data = json_decode(File::get($path), true);
|
||||||
|
|
||||||
|
foreach ($data as $item) {
|
||||||
|
DB::table('education')->insert([
|
||||||
|
'id' => $item['id'],
|
||||||
|
'opleiding' => $item['opleiding'],
|
||||||
|
'instituut' => $item['instituut'],
|
||||||
|
'startdatum' => $item['startdatum'],
|
||||||
|
'einddatum' => $item['einddatum'] ?? null,
|
||||||
|
'beschrijving' => $item['beschrijving'],
|
||||||
|
'created_at' => $item['created_at'] ?? now(),
|
||||||
|
'updated_at' => $item['updated_at'] ?? now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
database/seeders/MediaSeeder.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
|
class MediaSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$path = database_path('data/media.json');
|
||||||
|
|
||||||
|
if (!File::exists($path)) {
|
||||||
|
$this->command->warn("media.json niet gevonden, seeding overgeslagen.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::table('media')->truncate();
|
||||||
|
|
||||||
|
$data = json_decode(File::get($path), true);
|
||||||
|
|
||||||
|
foreach ($data as $item) {
|
||||||
|
DB::table('media')->insert([
|
||||||
|
// 'id' => $item['id'],
|
||||||
|
'model_type' => $item['model_type'],
|
||||||
|
'model_id' => $item['model_id'],
|
||||||
|
'uuid' => $item['uuid'],
|
||||||
|
'collection_name' => $item['collection_name'],
|
||||||
|
'name' => $item['name'],
|
||||||
|
'file_name' => $item['file_name'],
|
||||||
|
'mime_type' => $item['mime_type'],
|
||||||
|
'disk' => $item['disk'],
|
||||||
|
'conversions_disk' => $item['conversions_disk'],
|
||||||
|
'size' => $item['size'],
|
||||||
|
'manipulations' => json_encode($item['manipulations']),
|
||||||
|
'custom_properties' => json_encode($item['custom_properties']),
|
||||||
|
'generated_conversions' => json_encode($item['generated_conversions']),
|
||||||
|
'responsive_images' => json_encode($item['responsive_images']),
|
||||||
|
'order_column' => $item['order_column'] ?? null,
|
||||||
|
'created_at' => $item['created_at'] ?? now(),
|
||||||
|
'updated_at' => $item['updated_at'] ?? now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->command->info('Media succesvol geïmporteerd.');
|
||||||
|
}
|
||||||
|
}
|
||||||
38
database/seeders/PersonaliaSeeder.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use App\Models\Personalia;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
|
class PersonaliaSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$path = database_path('data/personalia.json');
|
||||||
|
|
||||||
|
if (!File::exists($path)) {
|
||||||
|
$this->command->warn("Bestand {$path} bestaat niet, seeder overgeslagen.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leegmaken van de bestaande data
|
||||||
|
Personalia::truncate();
|
||||||
|
|
||||||
|
// JSON inladen
|
||||||
|
$data = json_decode(File::get($path), true);
|
||||||
|
|
||||||
|
// Records toevoegen
|
||||||
|
foreach ($data as $item) {
|
||||||
|
Personalia::create([
|
||||||
|
'key' => $item['key'],
|
||||||
|
'value' => $item['value'],
|
||||||
|
'hidden' => $item['hidden'],
|
||||||
|
'icon' => $item['icon'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->command->info(count($data) . ' personalia-records geïmporteerd.');
|
||||||
|
}
|
||||||
|
}
|
||||||
37
database/seeders/SkillSeeder.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use App\Models\Skill;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
|
class SkillSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$path = database_path('data/skills.json');
|
||||||
|
|
||||||
|
if (!File::exists($path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verwijder alle bestaande records
|
||||||
|
Skill::truncate();
|
||||||
|
|
||||||
|
// Laad en decode de JSON
|
||||||
|
$data = json_decode(File::get($path), true);
|
||||||
|
|
||||||
|
// Voeg nieuwe data toe
|
||||||
|
foreach ($data as $item) {
|
||||||
|
Skill::create([
|
||||||
|
'type' => $item['type'],
|
||||||
|
'title' => $item['title'],
|
||||||
|
'description' => $item['description'] ?? null,
|
||||||
|
'rating' => $item['rating'] ?? null,
|
||||||
|
'created_at' => $item['created_at'] ?? now(),
|
||||||
|
'updated_at' => $item['updated_at'] ?? now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
database/seeders/WorkExperienceSeeder.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use App\Models\WorkExperience;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
|
class WorkExperienceSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$jsonPath = database_path('data/work_experiences.json');
|
||||||
|
|
||||||
|
// Bestaat het JSON-bestand?
|
||||||
|
if (!File::exists($jsonPath)) {
|
||||||
|
$this->command->warn("❌ Bestand $jsonPath niet gevonden. Seeder overgeslagen.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verwijder bestaande records
|
||||||
|
WorkExperience::truncate();
|
||||||
|
|
||||||
|
// Lees en decode de JSON
|
||||||
|
$json = File::get($jsonPath);
|
||||||
|
$data = json_decode($json, true);
|
||||||
|
|
||||||
|
// Voeg werkervaringen toe
|
||||||
|
foreach ($data as $item) {
|
||||||
|
WorkExperience::updateOrCreate(
|
||||||
|
[
|
||||||
|
'werkgever' => $item['werkgever'],
|
||||||
|
'functie' => $item['functie'],
|
||||||
|
'startdatum' => $item['startdatum'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'einddatum' => $item['einddatum'] ?? null,
|
||||||
|
'beschrijving' => $item['beschrijving'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->command->info("✅ Werkervaringen succesvol geïmporteerd.");
|
||||||
|
}
|
||||||
|
}
|
||||||
9
package-lock.json
generated
@@ -4,6 +4,9 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"stickybits": "^3.7.11"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/forms": "^0.5.2",
|
"@tailwindcss/forms": "^0.5.2",
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
@@ -3259,6 +3262,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/stickybits": {
|
||||||
|
"version": "3.7.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/stickybits/-/stickybits-3.7.11.tgz",
|
||||||
|
"integrity": "sha512-WO+ns7BYZqGS4jWVTg5JNhIvNV4LGbUtNTSck4zAkWRQzA1IfxwIkMGc0BbdGy4PGIjK7kKo5CZcN6Sd5dHVlw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/string-width": {
|
"node_modules/string-width": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||||
|
|||||||
@@ -17,5 +17,8 @@
|
|||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.31",
|
||||||
"tailwindcss": "^3.1.0",
|
"tailwindcss": "^3.1.0",
|
||||||
"vite": "^6.2.4"
|
"vite": "^6.2.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"stickybits": "^3.7.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,24 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
#custom-cursor {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 9999;
|
||||||
|
height: 30px;
|
||||||
|
width: auto;
|
||||||
|
display: inline-block;
|
||||||
|
transform: scaleX(-1) translate(-50%, -50%);
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#custom-cursor svg {
|
||||||
|
|
||||||
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,3 +5,12 @@ import Alpine from 'alpinejs';
|
|||||||
window.Alpine = Alpine;
|
window.Alpine = Alpine;
|
||||||
|
|
||||||
Alpine.start();
|
Alpine.start();
|
||||||
|
|
||||||
|
import stickybits from 'stickybits';
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
stickybits('#right-content', {
|
||||||
|
stickyBitStickyOffset: 40,
|
||||||
|
parent: '.grid' // dit moet de container zijn waarin sticky moet blijven
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (session('status') == 'verification-link-sent')
|
@if (session('status') == 'verification-link-sent')
|
||||||
<div class="mb-4 font-medium text-sm text-green-600 dark:text-green-400">
|
<div class="mb-4 font-medium text-sm text-green-600 dark:text-sitiweb-green">
|
||||||
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
|
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
@props(['status'])
|
@props(['status'])
|
||||||
|
|
||||||
@if ($status)
|
@if ($status)
|
||||||
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}>
|
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600 dark:text-sitiweb-green']) }}>
|
||||||
{{ $status }}
|
{{ $status }}
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
@@ -11,12 +11,12 @@
|
|||||||
<p class="text-sm text-gray-500 dark:text-gray-400">{{ $education->startdatum }} – {{ $education->einddatum ?? 'heden' }}</p>
|
<p class="text-sm text-gray-500 dark:text-gray-400">{{ $education->startdatum }} – {{ $education->einddatum ?? 'heden' }}</p>
|
||||||
<p class="mt-2 text-gray-700 dark:text-gray-300">{{ $education->beschrijving }}</p>
|
<p class="mt-2 text-gray-700 dark:text-gray-300">{{ $education->beschrijving }}</p>
|
||||||
|
|
||||||
@if ($education->getFirstMediaUrl('afbeelding'))
|
@if ($education->image())
|
||||||
<img src="{{ $education->getFirstMediaUrl('afbeelding') }}" class="mt-4 w-32 h-auto rounded" />
|
<img src="{{ $education->imageUrl() }}" class="mt-4 w-32 h-auto rounded" />
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div class="mt-4 space-x-2">
|
<div class="mt-4 space-x-2">
|
||||||
<a href="{{ route('educations.edit', $education) }}" class="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600">Bewerk</a>
|
<a href="{{ route('educations.edit', $education) }}" class="px-3 py-1 bg-green-400 text-white rounded hover:bg-blue-600">Bewerk</a>
|
||||||
|
|
||||||
<form action="{{ route('educations.destroy', $education) }}" method="POST" class="inline-block" onsubmit="return confirm('Weet je zeker dat je dit wilt verwijderen?')">
|
<form action="{{ route('educations.destroy', $education) }}" method="POST" class="inline-block" onsubmit="return confirm('Weet je zeker dat je dit wilt verwijderen?')">
|
||||||
@csrf
|
@csrf
|
||||||
|
|||||||
24
resources/views/frontend/_card.blade.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<div class="p-4 bg-white dark:bg-gray-800 rounded shadow">
|
||||||
|
<h3 class="text-lg font-bold text-gray-800 dark:text-white">{{ $skill->title }}</h3>
|
||||||
|
|
||||||
|
@if($skill->type === 'rating')
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-300 mb-2">Beoordeling: {{ $skill->rating }}/10</p>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($skill->description)
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-300">{{ $skill->description }}</p>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if ($skill->getFirstMediaUrl('image'))
|
||||||
|
<img src="{{ $skill->getFirstMediaUrl('image') }}" alt="{{ $skill->title }}" class="mt-2 max-w-full h-32 object-contain rounded">
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="mt-4 flex justify-between">
|
||||||
|
<a href="{{ route('skills.edit', $skill) }}" class="text-blue-600 hover:underline">Bewerken</a>
|
||||||
|
<form action="{{ route('skills.destroy', $skill) }}" method="POST" onsubmit="return confirm('Weet je zeker dat je dit wilt verwijderen?')">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button class="text-red-600 hover:underline">Verwijderen</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
115
resources/views/frontend/cta.blade.php
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<!-- Call to Action -->
|
||||||
|
<section
|
||||||
|
class="text-center lg:rounded-lg lg:bg-white lg:p-10 lg:shadow-xs lg:ring-1 lg:ring-zinc-950/5 dark:lg:bg-zinc-900 dark:lg:ring-white/10 space-y-4">
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold">
|
||||||
|
<i class="fa-solid fa-paper-plane mr-2 text-sitiweb-green"></i> Wat kan ik voor jou betekenen?
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p class="text-gray-600 dark:text-gray-300 text-sm">
|
||||||
|
📬 Ook beschikbaar voor freelance opdrachten of samenwerkingen. <br>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="flex justify-center gap-4 mt-4 flex-wrap">
|
||||||
|
<button onclick="openContactModal()"
|
||||||
|
class="px-5 py-2 bg-sitiweb-green text-white rounded-full text-sm font-medium hover:bg-green-700 transition">
|
||||||
|
<i class="fa-solid fa-envelope mr-2"></i> Contact opnemen
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Contact Modal -->
|
||||||
|
<div id="contact-modal" class="fixed inset-0 z-50 hidden bg-black/50 flex items-center justify-center">
|
||||||
|
<div class="bg-white dark:bg-zinc-900 rounded-lg shadow-lg max-w-md w-full p-6 space-y-4">
|
||||||
|
<h3 class="text-xl font-semibold text-zinc-800 dark:text-white">Stuur een bericht</h3>
|
||||||
|
<form id="contact-form" class="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label for="name" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300">Naam</label>
|
||||||
|
<input type="text" id="name" name="name" required
|
||||||
|
class="w-full mt-1 px-3 py-2 border border-zinc-300 rounded-md focus:outline-none focus:ring-2 focus:ring-sitiweb-green dark:bg-zinc-800 dark:border-zinc-600 dark:text-white" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="email" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300">E-mail
|
||||||
|
(optioneel)</label>
|
||||||
|
<input type="email" id="email" name="email"
|
||||||
|
class="w-full mt-1 px-3 py-2 border border-zinc-300 rounded-md focus:outline-none focus:ring-2 focus:ring-sitiweb-green dark:bg-zinc-800 dark:border-zinc-600 dark:text-white" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="phone" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300">Telefoonnummer
|
||||||
|
(optioneel)</label>
|
||||||
|
<input type="tel" id="phone" name="phone"
|
||||||
|
class="w-full mt-1 px-3 py-2 border border-zinc-300 rounded-md focus:outline-none focus:ring-2 focus:ring-sitiweb-green dark:bg-zinc-800 dark:border-zinc-600 dark:text-white" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="message" class="block text-sm font-medium text-zinc-700 dark:text-zinc-300">Bericht</label>
|
||||||
|
<textarea id="message" name="message" required rows="4"
|
||||||
|
class="w-full mt-1 px-3 py-2 border border-zinc-300 rounded-md focus:outline-none focus:ring-2 focus:ring-sitiweb-green dark:bg-zinc-800 dark:border-zinc-600 dark:text-white"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<button type="button" onclick="closeContactModal()"
|
||||||
|
class="px-4 py-2 text-sm bg-zinc-200 text-zinc-800 rounded-md hover:bg-zinc-300 dark:bg-zinc-700 dark:text-white dark:hover:bg-zinc-600">
|
||||||
|
Annuleren
|
||||||
|
</button>
|
||||||
|
<button type="submit"
|
||||||
|
class="px-4 py-2 text-sm bg-sitiweb-green text-white rounded-md hover:bg-green-700">
|
||||||
|
Versturen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
function openContactModal() {
|
||||||
|
document.getElementById('contact-modal').classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeContactModal() {
|
||||||
|
document.getElementById('contact-modal').classList.add('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('contact-form').addEventListener('submit', async function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const name = document.getElementById('name').value.trim();
|
||||||
|
const message = document.getElementById('message').value.trim();
|
||||||
|
const email = document.getElementById('email').value.trim();
|
||||||
|
const phone = document.getElementById('phone').value.trim();
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/contact', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute(
|
||||||
|
'content'),
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
name,
|
||||||
|
message,
|
||||||
|
email,
|
||||||
|
phone
|
||||||
|
}),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
alert('Bericht succesvol verzonden!');
|
||||||
|
closeContactModal();
|
||||||
|
this.reset();
|
||||||
|
} else {
|
||||||
|
alert('Er ging iets mis bij het verzenden.');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Fout:', error);
|
||||||
|
alert('Netwerkfout bij verzenden.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
@@ -1,9 +1,19 @@
|
|||||||
@foreach ($education as $item)
|
@foreach ($education as $item)
|
||||||
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow space-y-2">
|
<hr role="presentation" class="w-full border-t border-zinc-950/10 dark:border-white/10 my-8">
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
@if ($item->image())
|
||||||
|
<img src="{{ $item->imageUrl() }}" alt="{{ $item->title }}"
|
||||||
|
class="w-12 h-12 rounded-md shadow-md object-contain bg-white dark:bg-gray-700 p-1">
|
||||||
|
@endif
|
||||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white">
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white">
|
||||||
|
|
||||||
|
|
||||||
{{ $item->opleiding }}
|
{{ $item->opleiding }}
|
||||||
<span class="teitemxt-gray-500 dark:text-gray-400 font-normal">– {{ $item->instituut }}</span>
|
<span class="teitemxt-gray-500 dark:text-gray-400 font-normal">– {{ $item->instituut }}</span>
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p class="text-sm text-gray-600 dark:text-gray-300 italic">
|
<p class="text-sm text-gray-600 dark:text-gray-300 italic">
|
||||||
{{ \Carbon\Carbon::parse($item->startdatum)->translatedFormat('Y') }}
|
{{ \Carbon\Carbon::parse($item->startdatum)->translatedFormat('Y') }}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<ul class="space-y-4">
|
<ul class="space-y-4">
|
||||||
@foreach ($personalia as $item)
|
@foreach ($personalia as $item)
|
||||||
<li class="flex items-start gap-4">
|
<li class="flex items-start gap-4 hover:scale-105 transition hover:shadow-lg">
|
||||||
<i class="fa fa-{{ $item->icon }} text-blue-600 text-xl mt-1"></i>
|
<i class="fa fa-{{ $item->icon }} text-gray-800 dark:text-gray-400 text-xl mt-1"></i>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p class="text-sm font-semibold text-gray-700 dark:text-gray-200">{{ ucfirst($item->key) }}</p>
|
<p class="text-sm font-semibold text-gray-700 dark:text-gray-200">{{ ucfirst($item->key) }}</p>
|
||||||
@@ -31,14 +31,9 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class="text-gray-500 text-left dark:text-gray-400 hover:text-gray-800 dark:hover:text-white font-mono"
|
class="text-gray-500 text-left dark:text-gray-400 hover:text-gray-800 dark:hover:text-white font-mono"
|
||||||
onclick="revealValue({{ $item->id }}, this)"
|
onclick="revealValue({{ $item->id }}, this)" data-placeholder="{{ $masked }}">
|
||||||
data-placeholder="{{ $masked }}"
|
|
||||||
>
|
|
||||||
{{ $masked }}
|
{{ $masked }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@else
|
@else
|
||||||
<p class="text-gray-800 dark:text-white">{{ $item->value }}</p>
|
<p class="text-gray-800 dark:text-white">{{ $item->value }}</p>
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
@if (isset($skills['tag']))
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
@foreach ($skills['tag'] as $skill)
|
||||||
|
<span
|
||||||
|
class="inline-block hover:scale-105 transition hover:shadow-lg bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-100 text-sm px-3 py-1 rounded">
|
||||||
|
|
||||||
|
{{ $skill->title }}
|
||||||
|
</span>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if (isset($skills['rating']))
|
||||||
|
|
||||||
|
@foreach ($skills['rating'] as $skill)
|
||||||
|
<hr role="presentation" class="w-full border-t border-zinc-950/10 dark:border-white/10 my-8">
|
||||||
|
<div class="space-y-4 flex flex-col gap-4">
|
||||||
|
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
@if ($skill->image())
|
||||||
|
<img src="{{ $skill->imageUrl() }}" alt="{{ $skill->title }}"
|
||||||
|
class="w-12 h-12 rounded-md shadow-md object-contain bg-white dark:bg-gray-700 p-1 hover:scale-125 transition hover:shadow-lg">
|
||||||
|
@endif
|
||||||
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white">
|
||||||
|
{{ $skill->title }}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Rating bar --}}
|
||||||
|
<div>
|
||||||
|
<div class="text-sm text-gray-600 dark:text-gray-300 italic mb-1">
|
||||||
|
Beoordeling: {{ $skill->rating }}/10
|
||||||
|
</div>
|
||||||
|
<div class="w-full h-3 bg-gray-300 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||||
|
<div class="h-full bg-sitiweb-green transition-all duration-300"
|
||||||
|
style="width: {{ $skill->rating * 10 }}%">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if ($skill->description)
|
||||||
|
<div class="text-gray-800 dark:text-gray-100 prose dark:prose-invert max-w-prose text-sm">
|
||||||
|
{!! nl2br(e($skill->description)) !!}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
@endif
|
||||||
|
|
||||||
|
|
||||||
|
@if (isset($skills['other']))
|
||||||
|
<div class="flex flex-wrap gap-4 mt-8">
|
||||||
|
@foreach ($skills['other'] as $skill)
|
||||||
|
<div class="flex flex-col items-center w-16">
|
||||||
|
|
||||||
|
@if ($skill->getFirstMediaUrl('image'))
|
||||||
|
<img src="{{ $skill->getFirstMediaUrl('image') }}" alt="{{ $skill->title }}"
|
||||||
|
class="w-10 h-10 object-contain mb-1 hover:scale-125 transition hover:shadow-lg" >
|
||||||
|
@endif
|
||||||
|
<span class="text-xs text-center text-gray-700 dark:text-gray-300">{{ $skill->title }}</span>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
@foreach ($experience as $item)
|
@foreach ($experience as $item)
|
||||||
<div class="bg-white dark:bg-gray-800 p-6 rounded-xl shadow space-y-2">
|
<hr role="presentation" class="w-full border-t border-zinc-950/10 dark:border-white/10 my-8">
|
||||||
|
<div class=" space-y-2">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
@if ($item->image())
|
||||||
|
<img src="{{ $item->imageUrl() }}" alt="{{ $item->title }}"
|
||||||
|
class="w-12 h-12 rounded-md shadow-md object-contain bg-white dark:bg-gray-700 p-1">
|
||||||
|
@endif
|
||||||
<h3 class="text-xl font-bold text-gray-900 dark:text-white">
|
<h3 class="text-xl font-bold text-gray-900 dark:text-white">
|
||||||
{{ $item->functie }} <span class="text-gray-500 dark:text-gray-400 font-normal">bij {{ $item->werkgever }}</span>
|
{{ $item->functie }} <span class="text-gray-500 dark:text-gray-400 font-normal">bij
|
||||||
|
{{ $item->werkgever }}</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p class="text-sm text-gray-600 dark:text-gray-300 italic">
|
<p class="text-sm text-gray-600 dark:text-gray-300 italic">
|
||||||
{{ \Carbon\Carbon::parse($item->startdatum)->translatedFormat('F Y') }}
|
{{ \Carbon\Carbon::parse($item->startdatum)->translatedFormat('F Y') }}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
@stack('scripts')
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
@if (session('status') === 'verification-link-sent')
|
@if (session('status') === 'verification-link-sent')
|
||||||
<p class="mt-2 font-medium text-sm text-green-600 dark:text-green-400">
|
<p class="mt-2 font-medium text-sm text-green-600 dark:text-sitiweb-green">
|
||||||
{{ __('A new verification link has been sent to your email address.') }}
|
{{ __('A new verification link has been sent to your email address.') }}
|
||||||
</p>
|
</p>
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
@@ -1,24 +1,57 @@
|
|||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label for="type" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Type</label>
|
||||||
|
<select id="type" name="type" class="mt-1 w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded">
|
||||||
|
<option value="rating" @selected(old('type', $skill->type ?? 'rating') === 'rating')>Rating</option>
|
||||||
|
<option value="tag" @selected(old('type', $skill->type ?? '') === 'tag')>Tag</option>
|
||||||
|
<option value="other" @selected(old('type', $skill->type ?? '') === 'other')>Overig</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Titel</label>
|
<label for="title" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Titel</label>
|
||||||
<input type="text" id="title" name="title" value="{{ old('title', $skill->title ?? '') }}" class="mt-1 w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded">
|
<input type="text" id="title" name="title" value="{{ old('title', $skill->title ?? '') }}" class="mt-1 w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div id="description-field">
|
||||||
|
|
||||||
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Beschrijving</label>
|
<label for="description" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Beschrijving</label>
|
||||||
<textarea id="description" name="description" rows="4" class="mt-1 w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded">{{ old('description', $skill->description ?? '') }}</textarea>
|
<textarea id="description" name="description" rows="4" class="mt-1 w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded">{{ old('description', $skill->description ?? '') }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div id="rating-field">
|
||||||
<label for="rating" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Beoordeling (1–10)</label>
|
<label for="rating" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Beoordeling (1–10)</label>
|
||||||
<input type="number" id="rating" name="rating" min="1" max="10" value="{{ old('rating', $skill->rating ?? 5) }}" class="mt-1 w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded">
|
<input type="number" id="rating" name="rating" min="1" max="10" value="{{ old('rating', $skill->rating ?? 5) }}" class="mt-1 w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div id="image-field">
|
||||||
<label for="image" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Afbeelding</label>
|
<label for="image" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Afbeelding</label>
|
||||||
<input type="file" id="image" name="image" class="mt-1 text-gray-800 dark:text-gray-100">
|
<input type="file" id="image" name="image" class="mt-1 text-gray-800 dark:text-gray-100">
|
||||||
@if (!empty($skill) && $skill->getFirstMediaUrl('image'))
|
@if (!empty($skill) && $skill->getFirstMediaUrl('image'))
|
||||||
<img src="{{ $skill->getFirstMediaUrl('image') }}" class="mt-2 max-w-xs rounded">
|
<img src="{{ $skill->getFirstMediaUrl('image') }}" class="mt-2 max-w-xs rounded">
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@push('scripts')
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleFields() {
|
||||||
|
const type = document.getElementById('type').value;
|
||||||
|
|
||||||
|
// Rating alleen tonen bij type = rating
|
||||||
|
document.getElementById('rating-field').style.display = (type === 'rating') ? 'block' : 'none';
|
||||||
|
|
||||||
|
// Image tonen bij rating en other
|
||||||
|
document.getElementById('image-field').style.display = (type === 'rating' || type === 'other') ? 'block' : 'none';
|
||||||
|
|
||||||
|
// Beschrijving alleen tonen bij rating
|
||||||
|
document.getElementById('description-field').style.display = (type === 'rating') ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
document.getElementById('type').addEventListener('change', toggleFields);
|
||||||
|
toggleFields(); // initial
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
@endpush
|
||||||
|
|||||||
@@ -1,27 +1,51 @@
|
|||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<div class="p-6">
|
<div class="p-6 space-y-10">
|
||||||
<h2 class="text-2xl font-semibold text-gray-800 dark:text-white mb-4">Vaardigheden</h2>
|
<h2 class="text-2xl font-semibold text-gray-800 dark:text-white">Vaardigheden</h2>
|
||||||
<a href="{{ route('skills.create') }}" class="mb-4 inline-block px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">Nieuwe vaardigheid</a>
|
|
||||||
|
|
||||||
|
<a href="{{ route('skills.create') }}" class="inline-block px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
|
||||||
|
Nieuwe vaardigheid
|
||||||
|
</a>
|
||||||
|
|
||||||
|
@php
|
||||||
|
$groupedSkills = $skills->groupBy('type');
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
{{-- Rating --}}
|
||||||
|
@if($groupedSkills->has('rating'))
|
||||||
|
<div>
|
||||||
|
<h3 class="text-xl font-bold text-gray-700 dark:text-gray-200 mb-4">Ratings</h3>
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
@foreach ($skills as $skill)
|
@foreach ($groupedSkills['rating'] as $skill)
|
||||||
<div class="p-4 bg-white dark:bg-gray-800 rounded shadow">
|
@include('frontend._card', ['skill' => $skill])
|
||||||
<h3 class="text-lg font-bold text-gray-800 dark:text-white">{{ $skill->title }}</h3>
|
|
||||||
<p class="text-sm text-gray-600 dark:text-gray-300 mb-2">Beoordeling: {{ $skill->rating }}/10</p>
|
|
||||||
<p class="text-sm text-gray-600 dark:text-gray-300">{{ $skill->description }}</p>
|
|
||||||
@if ($skill->getFirstMediaUrl('image'))
|
|
||||||
<img src="{{ $skill->getFirstMediaUrl('image') }}" alt="{{ $skill->title }}" class="mt-2 max-w-full h-32 object-contain rounded">
|
|
||||||
@endif
|
|
||||||
<div class="mt-4 flex justify-between">
|
|
||||||
<a href="{{ route('skills.edit', $skill) }}" class="text-blue-600 hover:underline">Bewerken</a>
|
|
||||||
<form action="{{ route('skills.destroy', $skill) }}" method="POST" onsubmit="return confirm('Weet je zeker dat je dit wilt verwijderen?')">
|
|
||||||
@csrf
|
|
||||||
@method('DELETE')
|
|
||||||
<button class="text-red-600 hover:underline">Verwijderen</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Tags --}}
|
||||||
|
@if($groupedSkills->has('tag'))
|
||||||
|
<div>
|
||||||
|
<h3 class="text-xl font-bold text-gray-700 dark:text-gray-200 mb-4">Tags</h3>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
@foreach ($groupedSkills['tag'] as $skill)
|
||||||
|
<span class="inline-block bg-blue-100 dark:bg-blue-800 text-blue-800 dark:text-blue-100 text-sm px-3 py-1 rounded">
|
||||||
|
{{ $skill->title }}
|
||||||
|
</span>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Overig --}}
|
||||||
|
@if($groupedSkills->has('other'))
|
||||||
|
<div>
|
||||||
|
<h3 class="text-xl font-bold text-gray-700 dark:text-gray-200 mb-4">Overige vaardigheden</h3>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
@foreach ($groupedSkills['other'] as $skill)
|
||||||
|
@include('frontend._card', ['skill' => $skill])
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
<div>
|
<div>
|
||||||
<label for="werkgever" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Werkgever</label>
|
<label for="werkgever" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Werkgever</label>
|
||||||
@@ -32,6 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<label for="beschrijving" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Beschrijving</label>
|
<label for="beschrijving" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Beschrijving</label>
|
||||||
<textarea id="beschrijving" name="beschrijving" rows="4" class="mt-1 w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded">{{ old('beschrijving', $workExperience->beschrijving ?? '') }}</textarea>
|
<textarea id="beschrijving" name="beschrijving" rows="4" class="mt-1 w-full px-3 py-2 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-700 rounded">{{ old('beschrijving', $workExperience->beschrijving ?? '') }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,8 +42,9 @@
|
|||||||
<div>
|
<div>
|
||||||
<label for="afbeelding" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Afbeelding</label>
|
<label for="afbeelding" class="block text-sm font-medium text-gray-700 dark:text-gray-200">Afbeelding</label>
|
||||||
<input type="file" id="afbeelding" name="afbeelding" class="mt-1 text-gray-800 dark:text-gray-100">
|
<input type="file" id="afbeelding" name="afbeelding" class="mt-1 text-gray-800 dark:text-gray-100">
|
||||||
@if (!empty($workExperience) && $workExperience->getFirstMediaUrl('afbeelding'))
|
|
||||||
<img src="{{ $workExperience->getFirstMediaUrl('afbeelding') }}" class="mt-2 max-w-xs rounded">
|
@if (!empty($workExperience) && $workExperience->image())
|
||||||
|
<img src="{{ $workExperience->imageUrl() }}" class="mt-2 max-w-xs rounded">
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (session('success'))
|
@if (session('success'))
|
||||||
<div class="mb-4 text-green-700 dark:text-green-400">{{ session('success') }}</div>
|
<div class="mb-4 text-green-700 dark:text-sitiweb-green">{{ session('success') }}</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<p class="mt-2 text-gray-700 dark:text-gray-200">{{ $experience->beschrijving }}</p>
|
<p class="mt-2 text-gray-700 dark:text-gray-200">{{ $experience->beschrijving }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<a href="{{ route('work-experiences.edit', $experience) }}" class="text-blue-500 hover:underline">Bewerken</a>
|
<a href="{{ route('work-experiences.edit', $experience) }}" class="text-sitiweb-green hover:underline">Bewerken</a>
|
||||||
<form method="POST" action="{{ route('work-experiences.destroy', $experience) }}">
|
<form method="POST" action="{{ route('work-experiences.destroy', $experience) }}">
|
||||||
@csrf
|
@csrf
|
||||||
@method('DELETE')
|
@method('DELETE')
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@if ($experience->getFirstMediaUrl('afbeelding'))
|
@if ($experience->image())
|
||||||
<img src="{{ $experience->getFirstMediaUrl('afbeelding') }}" class="mt-4 max-w-xs rounded">
|
<img src="{{ $experience->imageUrl() }}" class="mt-4 max-w-xs rounded">
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|||||||
@@ -11,12 +11,8 @@ Route::get('/', [FrontendController::class, 'index'])->name('home');
|
|||||||
Route::get('/dashboard', function () {
|
Route::get('/dashboard', function () {
|
||||||
return view('dashboard');
|
return view('dashboard');
|
||||||
})->middleware(['auth', 'verified'])->name('dashboard');
|
})->middleware(['auth', 'verified'])->name('dashboard');
|
||||||
Route::get('/getPersonalia/{id}', function ($id) {
|
Route::get('/getPersonalia/{id}', [FrontendController::class, 'getPersonalia'])->name('personalia');
|
||||||
$item = \App\Models\Personalia::findOrFail($id);
|
Route::post('/contact', [FrontendController::class, 'message'])->name('contact');
|
||||||
return response()->json([
|
|
||||||
'value' => $item->value,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::middleware('auth')->group(function () {
|
Route::middleware('auth')->group(function () {
|
||||||
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
|
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
|
||||||
|
|||||||
50
storage/app/.gitignore
vendored
@@ -1,4 +1,46 @@
|
|||||||
*
|
# Alles negeren
|
||||||
!private/
|
/public/*
|
||||||
!public/
|
|
||||||
!.gitignore
|
# Uitzonderingen (wél toevoegen aan Git)
|
||||||
|
!public/1/
|
||||||
|
!public/2/
|
||||||
|
!public/3/
|
||||||
|
!public/4/
|
||||||
|
!public/5/
|
||||||
|
!public/6/
|
||||||
|
!public/7/
|
||||||
|
!public/8/
|
||||||
|
!public/9/
|
||||||
|
!public/10/
|
||||||
|
!public/11/
|
||||||
|
!public/12/
|
||||||
|
!public/13/
|
||||||
|
!public/14/
|
||||||
|
!public/15/
|
||||||
|
!public/16/
|
||||||
|
!public/17/
|
||||||
|
!public/18/
|
||||||
|
!public/19/
|
||||||
|
!public/20/
|
||||||
|
!public/21/
|
||||||
|
!public/22/
|
||||||
|
!public/23/
|
||||||
|
!public/24/
|
||||||
|
!public/25/
|
||||||
|
!public/26/
|
||||||
|
!public/27/
|
||||||
|
!public/28/
|
||||||
|
!public/29/
|
||||||
|
!public/30/
|
||||||
|
!public/31/
|
||||||
|
!public/32/
|
||||||
|
!public/33/
|
||||||
|
!public/34/
|
||||||
|
!public/35/
|
||||||
|
!public/36/
|
||||||
|
!public/37/
|
||||||
|
!public/38/
|
||||||
|
|
||||||
|
# Specifieke losse bestanden
|
||||||
|
!public/roberto.png
|
||||||
|
!public/sitiweb.svg
|
||||||
|
|||||||
2
storage/app/public/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
*
|
|
||||||
!.gitignore
|
|
||||||
BIN
storage/app/public/1/jumbo.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
storage/app/public/10/inh.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
storage/app/public/11/git-logo.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
storage/app/public/12/lara.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
storage/app/public/13/Livewire-logo.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
storage/app/public/14/Tailwind-CSS.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
storage/app/public/15/Postman.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
storage/app/public/16/Docker.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
storage/app/public/17/proxmox-logo.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
storage/app/public/18/Grafana.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
storage/app/public/19/Cloudflare.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
storage/app/public/2/php-logo.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
storage/app/public/20/directadmnin-logo.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
storage/app/public/21/MySQL.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
storage/app/public/22/Uptime-Kuma-Logo.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
storage/app/public/23/NGINX.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
storage/app/public/24/Visual-Studio-Code-(VS-Code).png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
storage/app/public/25/GIMP.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
storage/app/public/26/WordPress.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
storage/app/public/27/WooCommerce.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
storage/app/public/28/Vaultwarden--Streamline-Simple-Icons.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
storage/app/public/29/healthchecks.logo.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
storage/app/public/3/sitiweb-logo.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
storage/app/public/30/GitLab.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
storage/app/public/31/GitHub.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
storage/app/public/32/Fedora.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
storage/app/public/33/Ubuntu.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
storage/app/public/34/CentOS.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
storage/app/public/35/Debian.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
storage/app/public/36/Composer.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
storage/app/public/37/NPM.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
storage/app/public/38/HTML5.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
storage/app/public/4/5848152fcef1014c0b5e4967.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
storage/app/public/5/JavaScript.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
storage/app/public/6/images.jpg
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
storage/app/public/7/internettoday-logo.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
storage/app/public/8/hr.jpg
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
storage/app/public/9/linux-logo.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
storage/app/public/roberto.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
2
storage/app/public/sitiweb.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" id="svg2" xml:space="preserve" viewBox="0 0 406.66666 473.33334" sodipodi:docname="Beeldmerk.ai"><metadata id="metadata8"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata><defs id="defs6"/><sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="640" inkscape:window-height="480" id="namedview4"/><g id="g10" inkscape:groupmode="layer" inkscape:label="Beeldmerk" transform="matrix(1.3333333,0,0,-1.3333333,0,473.33333)"><g id="g12" transform="translate(192.9405,297.8561)"><path d="M 0,0 3.661,-204.853 95.917,-260.941 95.291,47.32 Z" style="fill:#009000;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path14"/></g><g id="g16" transform="translate(287.7484,238.091)"><path d="M 0,0 -183.898,-87.583 -275.154,-31.495 1.239,108.114 Z" style="fill:#00ab00;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path18"/></g><g id="g20" transform="translate(172.7637,52.3648)"><path d="M 0,0 -93.429,-43.886 -96.399,59 -2.97,102.886 Z" style="fill:#ee0004;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path22"/></g><g id="g24" transform="translate(169.794,155.2513)"><path d="m 0,0 2.97,-102.886 -93.429,-43.887" style="fill:#d8000e;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path26"/></g></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -14,6 +14,9 @@ export default {
|
|||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: ['Figtree', ...defaultTheme.fontFamily.sans],
|
sans: ['Figtree', ...defaultTheme.fontFamily.sans],
|
||||||
},
|
},
|
||||||
|
colors: {
|
||||||
|
'sitiweb-green': '#00AB00',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||