DONE: digital card with profile display: WIP: membership condition on letter, is_first_time column in users table
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\User\Services;
|
||||
|
||||
use BaconQrCode\Renderer\Image\SvgImageBackEnd;
|
||||
use BaconQrCode\Renderer\ImageRenderer;
|
||||
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
|
||||
use BaconQrCode\Writer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Modules\Auth\Entities\User;
|
||||
use Spatie\Browsershot\Browsershot;
|
||||
|
||||
class MemberDigitalCardService
|
||||
{
|
||||
public const CARD_WIDTH = 840;
|
||||
|
||||
public const CARD_HEIGHT = 540;
|
||||
|
||||
public function renderPng(User $user, string $side): string
|
||||
{
|
||||
$view = $side === 'belakang'
|
||||
? 'user::digital-card.back'
|
||||
: 'user::digital-card.front';
|
||||
|
||||
$html = View::make($view, $this->prepareViewData($user))->render();
|
||||
|
||||
return $this->makeBrowsershot($html)->screenshot();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function prepareViewData(User $user): array
|
||||
{
|
||||
$user = app(PublicMemberProfileService::class)->loadVerifiableRelations($user);
|
||||
$user->ensurePublicProfileToken();
|
||||
|
||||
$currentEmployment = $user->employments->firstWhere('is_current', true)
|
||||
?? $user->employments->first();
|
||||
|
||||
$logoPath = config('user.digital_card_logo_path');
|
||||
$profileUrl = rtrim(config('user.frontend_url'), '/').'/v/'.$user->public_profile_token;
|
||||
|
||||
return [
|
||||
'memberNumber' => $this->displayCardValue($user->member_number),
|
||||
'memberName' => $user->name ?: '-',
|
||||
'memberType' => $this->displayCardValue($user->member_type),
|
||||
'companyName' => $this->displayCardValue($currentEmployment?->company_name),
|
||||
'avatarDataUri' => $this->resolveStorageDataUri($user->image_url),
|
||||
'avatarInitials' => $this->avatarInitials($user->name),
|
||||
'logoDataUri' => $this->resolveFileDataUri($logoPath),
|
||||
'profileUrl' => $profileUrl,
|
||||
'qrDataUri' => $this->generateQrDataUri($profileUrl),
|
||||
];
|
||||
}
|
||||
|
||||
protected function makeBrowsershot(string $html): Browsershot
|
||||
{
|
||||
$browsershot = Browsershot::html($html)
|
||||
->setNodeModulePath(config('browsershot.node_module_path'))
|
||||
->timeout(config('browsershot.timeout'))
|
||||
->windowSize(self::CARD_WIDTH, self::CARD_HEIGHT)
|
||||
->deviceScaleFactor(2)
|
||||
->showBackground();
|
||||
|
||||
if ($nodeBinary = config('browsershot.node_binary')) {
|
||||
$browsershot->setNodeBinary($nodeBinary);
|
||||
}
|
||||
|
||||
if ($npmBinary = config('browsershot.npm_binary')) {
|
||||
$browsershot->setNpmBinary($npmBinary);
|
||||
}
|
||||
|
||||
if ($chromePath = config('browsershot.chrome_path')) {
|
||||
$browsershot->setChromePath($chromePath);
|
||||
}
|
||||
|
||||
if (config('browsershot.no_sandbox')) {
|
||||
$browsershot->noSandbox();
|
||||
}
|
||||
|
||||
return $browsershot;
|
||||
}
|
||||
|
||||
protected function generateQrDataUri(string $content): string
|
||||
{
|
||||
$renderer = new ImageRenderer(
|
||||
new RendererStyle(220, 1),
|
||||
new SvgImageBackEnd
|
||||
);
|
||||
$writer = new Writer($renderer);
|
||||
$svg = $writer->writeString($content);
|
||||
|
||||
return 'data:image/svg+xml;base64,'.base64_encode($svg);
|
||||
}
|
||||
|
||||
protected function resolveFileDataUri(?string $path): ?string
|
||||
{
|
||||
if (empty($path) || ! file_exists($path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$mime = mime_content_type($path) ?: 'image/svg+xml';
|
||||
|
||||
return 'data:'.$mime.';base64,'.base64_encode(file_get_contents($path));
|
||||
}
|
||||
|
||||
protected function resolveStorageDataUri(?string $path): ?string
|
||||
{
|
||||
if (blank($path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$fullPath = Storage::disk('public')->path($path);
|
||||
|
||||
return $this->resolveFileDataUri($fullPath);
|
||||
}
|
||||
|
||||
protected function avatarInitials(?string $name): string
|
||||
{
|
||||
$trimmed = trim((string) $name);
|
||||
|
||||
if ($trimmed === '') {
|
||||
return '--';
|
||||
}
|
||||
|
||||
return strtoupper(mb_substr($trimmed, 0, 2));
|
||||
}
|
||||
|
||||
protected function displayCardValue(mixed $value): string
|
||||
{
|
||||
if ($value === null || $value === '') {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$trimmed = trim((string) $value);
|
||||
|
||||
return $trimmed !== '' ? $trimmed : '-';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user