Fix ABHA card barcode print rendering
This commit is contained in:
parent
f7a0beadb2
commit
ee9bb7b560
|
|
@ -454,6 +454,7 @@ class Abha extends BaseController
|
|||
$mobileVerified = (int) ($patient['abha_mobile_verified'] ?? 0) === 1;
|
||||
$abhaQrUrl = 'https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=' . urlencode($abhaNumClean);
|
||||
$barcodeSvg = $this->buildCode39Svg($hmsId);
|
||||
$barcodeImage = $this->buildCode39ImageDataUri($hmsId, $barcodeSvg);
|
||||
|
||||
return view('abha/card', [
|
||||
'patient' => $patient,
|
||||
|
|
@ -468,6 +469,7 @@ class Abha extends BaseController
|
|||
'brand_name' => (string) ($hospitalBrand['brand_name'] ?? 'HMS'),
|
||||
'hms_id' => $hmsId,
|
||||
'hms_barcode_svg' => $barcodeSvg,
|
||||
'hms_barcode_image' => $barcodeImage,
|
||||
'profile_photo_url' => $profilePhotoUrl,
|
||||
'abha_qr_url' => $abhaQrUrl,
|
||||
'patient_mobile' => $mobileNo,
|
||||
|
|
@ -591,10 +593,76 @@ class Abha extends BaseController
|
|||
}
|
||||
|
||||
private function buildCode39Svg(string $value): string
|
||||
{
|
||||
$layout = $this->buildCode39Layout($value);
|
||||
if ($layout === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$rects = [];
|
||||
foreach ($layout['bars'] as $bar) {
|
||||
$rects[] = '<rect x="' . $bar['x'] . '" y="0" width="' . $bar['w'] . '" height="' . $layout['height'] . '" fill="#111" />';
|
||||
}
|
||||
|
||||
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' . $layout['width'] . ' ' . $layout['height'] . '" role="img" aria-label="HMS Barcode">'
|
||||
. implode('', $rects)
|
||||
. '</svg>';
|
||||
}
|
||||
|
||||
private function buildCode39ImageDataUri(string $value, string $svgFallback = ''): string
|
||||
{
|
||||
$layout = $this->buildCode39Layout($value);
|
||||
if ($layout === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (! function_exists('imagecreatetruecolor') || ! function_exists('imagepng')) {
|
||||
$svg = $svgFallback !== '' ? $svgFallback : $this->buildCode39Svg($value);
|
||||
return $svg !== '' ? 'data:image/svg+xml;base64,' . base64_encode($svg) : '';
|
||||
}
|
||||
|
||||
$img = imagecreatetruecolor($layout['width'], $layout['height']);
|
||||
if ($img === false) {
|
||||
$svg = $svgFallback !== '' ? $svgFallback : $this->buildCode39Svg($value);
|
||||
return $svg !== '' ? 'data:image/svg+xml;base64,' . base64_encode($svg) : '';
|
||||
}
|
||||
|
||||
$white = imagecolorallocate($img, 255, 255, 255);
|
||||
$black = imagecolorallocate($img, 17, 17, 17);
|
||||
imagefilledrectangle($img, 0, 0, $layout['width'], $layout['height'], $white);
|
||||
|
||||
foreach ($layout['bars'] as $bar) {
|
||||
imagefilledrectangle(
|
||||
$img,
|
||||
$bar['x'],
|
||||
0,
|
||||
$bar['x'] + $bar['w'] - 1,
|
||||
$layout['height'],
|
||||
$black
|
||||
);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
imagepng($img);
|
||||
$pngBinary = ob_get_clean();
|
||||
imagedestroy($img);
|
||||
|
||||
if (! is_string($pngBinary) || $pngBinary === '') {
|
||||
$svg = $svgFallback !== '' ? $svgFallback : $this->buildCode39Svg($value);
|
||||
return $svg !== '' ? 'data:image/svg+xml;base64,' . base64_encode($svg) : '';
|
||||
}
|
||||
|
||||
return 'data:image/png;base64,' . base64_encode($pngBinary);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{bars: list<array{x:int,w:int}>, width:int, height:int}|null
|
||||
*/
|
||||
private function buildCode39Layout(string $value): ?array
|
||||
{
|
||||
$normalized = strtoupper(trim($value));
|
||||
if ($normalized === '') {
|
||||
return '';
|
||||
return null;
|
||||
}
|
||||
|
||||
$supported = [
|
||||
|
|
@ -623,7 +691,7 @@ class Abha extends BaseController
|
|||
}
|
||||
|
||||
if ($clean === '') {
|
||||
return '';
|
||||
return null;
|
||||
}
|
||||
|
||||
$narrow = 2;
|
||||
|
|
@ -633,14 +701,14 @@ class Abha extends BaseController
|
|||
$gap = 2;
|
||||
|
||||
$x = $quiet;
|
||||
$rects = [];
|
||||
$bars = [];
|
||||
$cleanLen = strlen($clean);
|
||||
for ($i = 0; $i < $cleanLen; $i++) {
|
||||
$pattern = $supported[$clean[$i]];
|
||||
for ($j = 0; $j < 9; $j++) {
|
||||
$w = ($pattern[$j] === 'w') ? $wide : $narrow;
|
||||
if ($j % 2 === 0) {
|
||||
$rects[] = '<rect x="' . $x . '" y="0" width="' . $w . '" height="' . $height . '" fill="#111" />';
|
||||
$bars[] = ['x' => $x, 'w' => $w];
|
||||
}
|
||||
$x += $w;
|
||||
}
|
||||
|
|
@ -649,10 +717,11 @@ class Abha extends BaseController
|
|||
}
|
||||
}
|
||||
|
||||
$width = $x + $quiet;
|
||||
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' . $width . ' ' . $height . '" role="img" aria-label="HMS Barcode">'
|
||||
. implode('', $rects)
|
||||
. '</svg>';
|
||||
return [
|
||||
'bars' => $bars,
|
||||
'width' => $x + $quiet,
|
||||
'height' => $height,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -44,21 +44,20 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid #d5e4f7;
|
||||
border-radius: 10px;
|
||||
background: #f7fbff;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
min-width: 0;
|
||||
}
|
||||
.brand-wrap.right { background: #ffffff; }
|
||||
.brand-wrap.left { justify-content: flex-start; }
|
||||
.brand-logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
object-fit: contain;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
border: 1px solid #d7e5f8;
|
||||
background: transparent;
|
||||
border: none;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.brand-text { min-width: 0; line-height: 1.05; }
|
||||
|
|
@ -76,40 +75,25 @@
|
|||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.hospital-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
.hospital-mini-logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
object-fit: contain;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #cfe0f8;
|
||||
background: #fff;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.hospital-name {
|
||||
font-size: 13px;
|
||||
color: #1e4a82;
|
||||
min-width: 0;
|
||||
}
|
||||
.hospital-name strong { color: #0f3f7d; }
|
||||
.patient-id-strip {
|
||||
width: 180px;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border: 1px solid #d4e3f8;
|
||||
border-radius: 8px;
|
||||
padding: 4px 6px;
|
||||
padding: 6px 8px;
|
||||
text-align: center;
|
||||
flex: 0 0 auto;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
.patient-id-barcode {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.patient-id-strip svg { width: 100%; height: 28px; }
|
||||
.patient-id-label {
|
||||
font-size: 9px;
|
||||
color: #5f7291;
|
||||
|
|
@ -254,7 +238,7 @@ $profilePhotoUrl = (string) ($profile_photo_url ?? '/assets/images/no_image.svg'
|
|||
$profilePhotoUrlEsc = esc($profilePhotoUrl);
|
||||
$hmsId = esc($hms_id ?? '');
|
||||
$abhaQrUrl = esc($abha_qr_url ?? '');
|
||||
$barcodeSvg = (string) ($hms_barcode_svg ?? '');
|
||||
$barcodeImage = esc($hms_barcode_image ?? '');
|
||||
$patientMobile = esc($patient_mobile ?? '');
|
||||
$mobileVerified = (bool) ($mobile_verified ?? false);
|
||||
?>
|
||||
|
|
@ -279,19 +263,17 @@ $mobileVerified = (bool) ($mobile_verified ?? false);
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hospital-strip">
|
||||
<div class="hospital-info">
|
||||
<img class="hospital-mini-logo" src="<?= $hospitalLogo ?>" alt="Hospital Logo">
|
||||
<div class="hospital-name">Hospital: <strong><?= $hospitalName ?></strong></div>
|
||||
</div>
|
||||
<?php if ($barcodeSvg !== '' && $hmsId !== ''): ?>
|
||||
<?php if ($barcodeImage !== '' && $hmsId !== ''): ?>
|
||||
<div class="hospital-strip">
|
||||
<div class="patient-id-strip">
|
||||
<div class="patient-id-label">Patient ID Barcode</div>
|
||||
<div><?= $barcodeSvg ?></div>
|
||||
<?php if ($barcodeImage !== ''): ?>
|
||||
<img class="patient-id-barcode" src="<?= $barcodeImage ?>" alt="Patient ID Barcode">
|
||||
<?php endif; ?>
|
||||
<div class="patient-id-value"><?= $hmsId ?></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="patient-area">
|
||||
<div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user