2 Commits

Author SHA1 Message Date
Ümit Tunç d245055bf4 feat: add automated WebP conversion and resizing for hero background images 2026-06-02 06:44:57 +03:00
Ümit Tunç 9c4dc0ff11 style: add hover transition effects to glass card headings 2026-06-02 06:29:17 +03:00
2 changed files with 116 additions and 5 deletions
+103 -5
View File
@@ -75,17 +75,115 @@ class Setting extends Model
$this->attributes['value'] = $value ? '1' : '0'; $this->attributes['value'] = $value ? '1' : '0';
} }
/**
* Set value from different field names
*/
public function setValueFileAttribute($value) public function setValueFileAttribute($value)
{ {
// Filament bazen dosya yolunu array olarak döndürebilir, bu durumda ilk elemanı alıyoruz // Filament bazen dosya yolunu array olarak döndürebilir, bu durumda ilk elemanı alıyoruz
if (is_array($value)) { if (is_array($value)) {
$this->attributes['value'] = array_values($value)[0] ?? null; $filePath = array_values($value)[0] ?? null;
} else { } else {
$this->attributes['value'] = $value; $filePath = $value;
} }
if ($filePath && $this->key === 'hero_bg') {
$filePath = $this->processHeroBackground($filePath);
}
$this->attributes['value'] = $filePath;
}
/**
* Process the hero background image: convert to webp, resize if necessary, and compress.
*/
protected function processHeroBackground($filePath)
{
try {
$disk = \Illuminate\Support\Facades\Storage::disk('public');
if (!$disk->exists($filePath)) {
return $filePath;
}
$absolutePath = $disk->path($filePath);
// Get image info
$imageInfo = @getimagesize($absolutePath);
if (!$imageInfo) {
return $filePath;
}
$mimeType = $imageInfo['mime'];
// Create GD image resource based on mime type
switch ($mimeType) {
case 'image/jpeg':
case 'image/jpg':
$image = @imagecreatefromjpeg($absolutePath);
break;
case 'image/png':
$image = @imagecreatefrompng($absolutePath);
break;
case 'image/webp':
$image = @imagecreatefromwebp($absolutePath);
break;
case 'image/gif':
$image = @imagecreatefromgif($absolutePath);
break;
default:
return $filePath;
}
if (!$image) {
return $filePath;
}
// Preserve transparency or handle it for webp if needed
imagealphablending($image, true);
imagesavealpha($image, true);
$originalWidth = imagesx($image);
$originalHeight = imagesy($image);
// Target dimensions: Hero bg size, max width 1920px
$maxWidth = 1920;
if ($originalWidth > $maxWidth) {
$newWidth = $maxWidth;
$newHeight = (int) (($originalHeight / $originalWidth) * $maxWidth);
$resizedImage = imagecreatetruecolor($newWidth, $newHeight);
// Preserve transparency
imagealphablending($resizedImage, false);
imagesavealpha($resizedImage, true);
// Resize
imagecopyresampled($resizedImage, $image, 0, 0, 0, 0, $newWidth, $newHeight, $originalWidth, $originalHeight);
imagedestroy($image);
$image = $resizedImage;
}
// Generate new webp path
$pathInfo = pathinfo($filePath);
$newWebpPath = $pathInfo['dirname'] . '/' . $pathInfo['filename'] . '.webp';
$absoluteWebpPath = $disk->path($newWebpPath);
// Save as webp with 80% quality (excellent quality-to-size ratio)
if (imagewebp($image, $absoluteWebpPath, 80)) {
imagedestroy($image);
// If the file extension changed, delete the original file
if ($newWebpPath !== $filePath) {
$disk->delete($filePath);
}
return $newWebpPath;
}
imagedestroy($image);
} catch (\Exception $e) {
// Log error or fallback to original
\Illuminate\Support\Facades\Log::error('Hero background image processing failed: ' . $e->getMessage());
}
return $filePath;
} }
/** /**
@@ -74,6 +74,19 @@
filter: brightness(1.4); filter: brightness(1.4);
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
.glass-card h4 {
color: white;
transition: all 0.3s ease-in-out;
text-shadow: 0px 1px 10px #00000080;
}
.glass-card:hover h4 {
color: black;
transition: all 0.3s ease-in-out;
text-shadow: none;
}
.glass-card:hover svg { .glass-card:hover svg {
filter: brightness(0.8); filter: brightness(0.8);
} }