feat: add favicon support and update related configurations in SystemService, SystemRequest, and views for improved branding

This commit is contained in:
Yoga Pangestu 2026-06-20 11:01:32 +07:00
parent 6aa818e562
commit 67ee140ba7
8 changed files with 29 additions and 4 deletions

View File

@ -46,6 +46,7 @@ public function share(Request $request): array
'name' => fn () => app(SystemSettings::class)->app_name,
'address' => fn () => app(SystemSettings::class)->address,
'logo_url' => fn () => app(SystemService::class)->systemData()['logo_url'] ?? asset('assets/logo.png'),
'favicon_url' => fn () => app(SystemService::class)->systemData()['favicon_url'] ?? null,
'login_cover_url' => fn () => app(SystemService::class)->systemData()['login_cover_url'] ?? null,
'auth' => fn () => [
'user' => $request->user() ? [

View File

@ -24,8 +24,9 @@ public function rules(): array
'email' => ['required', 'email', 'max:100'],
'phone' => ['required', 'string', 'max:20', new PhoneNumber],
'address' => ['required', 'string'],
'logo' => ['required', 'image', 'max:2048'],
'login_cover' => ['required', 'image', 'max:5120'],
'logo' => ['nullable', 'image', 'max:2048'],
'favicon' => ['nullable', 'image', 'max:1024'],
'login_cover' => ['nullable', 'image', 'max:5120'],
];
}
@ -41,6 +42,7 @@ public function attributes(): array
'phone' => 'nomor telepon',
'address' => 'alamat',
'logo' => 'logo',
'favicon' => 'favicon',
'login_cover' => 'cover login',
];
}

View File

@ -29,6 +29,7 @@ public static function instance(): self
public function registerMediaCollections(): void
{
$this->addMediaCollection('logo')->singleFile();
$this->addMediaCollection('favicon')->singleFile();
$this->addMediaCollection('login_cover')->singleFile();
}
}

View File

@ -22,6 +22,7 @@ public function systemData(): array
$configuration->load('media');
$logo = MediaPresenter::first($configuration, 'logo');
$favicon = MediaPresenter::first($configuration, 'favicon');
$loginCover = MediaPresenter::first($configuration, 'login_cover');
return [
@ -31,6 +32,7 @@ public function systemData(): array
'phone' => $settings->phone,
'address' => $settings->address,
'logo_url' => $logo['url'] ?? null,
'favicon_url' => $favicon['url'] ?? null,
'login_cover_url' => $loginCover['url'] ?? null,
];
}
@ -51,6 +53,10 @@ public function updateSystem(array $validated): void
$this->mediaService->replaceSingleFile($configuration, $validated['logo'], 'logo', 'logo');
}
if (isset($validated['favicon']) && $validated['favicon'] instanceof UploadedFile) {
$this->mediaService->replaceSingleFile($configuration, $validated['favicon'], 'favicon', 'favicon');
}
if (isset($validated['login_cover']) && $validated['login_cover'] instanceof UploadedFile) {
$this->mediaService->replaceSingleFile($configuration, $validated['login_cover'], 'login_cover', 'login-cover');
}
@ -61,6 +67,10 @@ public function updateSystem(array $validated): void
$errors['logo'] = 'Logo wajib diisi.';
}
if (! $configuration->hasMedia('favicon')) {
$errors['favicon'] = 'Favicon wajib diisi.';
}
if (! $configuration->hasMedia('login_cover')) {
$errors['login_cover'] = 'Cover login wajib diisi.';
}

View File

@ -23,6 +23,7 @@ const form = useForm({
phone: props.data.phone ?? '',
address: props.data.address ?? '',
logo: null as File | null,
favicon: null as File | null,
login_cover: null as File | null,
});
@ -39,6 +40,10 @@ function buildFormData(): FormData {
formData.append('logo', form.logo);
}
if (form.favicon) {
formData.append('favicon', form.favicon);
}
if (form.login_cover) {
formData.append('login_cover', form.login_cover);
}
@ -119,11 +124,15 @@ function submit() {
</Field>
</FieldGroup>
<FieldGroup class="grid gap-6 sm:grid-cols-2">
<FieldGroup class="grid gap-6 sm:grid-cols-3">
<ImageUploadField id="logo" v-model="form.logo" label="Logo" required
description="Disarankan PNG transparan, maks. 2 MB." :current-url="data.logo_url"
:errors="formErrors(form, 'logo')" />
<ImageUploadField id="favicon" v-model="form.favicon" label="Favicon"
description="PNG/SVG, maks. 1 MB." :current-url="data.favicon_url"
:errors="formErrors(form, 'favicon')" />
<ImageUploadField id="login_cover" v-model="form.login_cover" label="Cover Login" required
description="Gambar latar halaman login, maks. 5 MB."
:current-url="data.login_cover_url" :errors="formErrors(form, 'login_cover')" />

View File

@ -26,6 +26,7 @@ declare module '@inertiajs/core' {
sidebarOpen: boolean;
appearance: 'light' | 'dark' | 'system';
logo_url: string | null;
favicon_url: string | null;
login_cover_url: string | null;
[key: string]: unknown;
};

View File

@ -19,6 +19,7 @@ export type SystemSettingsData = {
phone: string;
address: string;
logo_url: string;
favicon_url: string | null;
login_cover_url: string;
};

View File

@ -20,7 +20,7 @@
<meta name="description" content="{{ config('app.name', 'Laravel') }} - Progressive Web App">
<meta name="theme-color" content="#171717">
<link rel="icon" href="{{ $page['props']['logo_url'] ?? asset('assets/logo.png') }}" sizes="any">
<link rel="icon" href="{{ $page['props']['favicon_url'] ?? $page['props']['logo_url'] ?? asset('assets/logo.png') }}" sizes="any">
<link rel="manifest" href="/build/manifest.webmanifest">
@fonts