web-mooc/resources/views/curriculum/certificate/download.blade.php
2026-02-03 09:00:31 +07:00

348 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{ get_phrase('Download Certificate') }}</title>
<link rel="shortcut icon" href="{{ asset(get_frontend_settings('favicon')) }}" />
<script src="{{ asset('assets/frontend/default/js/jquery-3.7.1.min.js') }}"></script>
<script src="{{ asset('assets/global/html2canvas/html2canvas.min.js') }}"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
</head>
<body>
<style>
html, body{
overflow-x: hidden;
}
body {
position: relative;
}
.remove-item,
.ui-resizable-handle {
display: none !important;
}
.certificate-layout-module {
left: unset !important;
top: unset !important;
margin-left: auto !important;
margin-right: auto !important;
}
svg {
width: 100%;
height: 100%;
}
.certificate-page {
width: 1123px;
height: 794px;
}
.download-wrapper {
position: fixed;
bottom: 20px;
right: 20px;
display: flex;
gap: 15px;
z-index: 100;
}
.download-btn {
padding: 12px 24px;
border-radius: 8px;
color: #ffffff;
background: linear-gradient(135deg, #3d9bff 0%, #0066cc 100%);
border: none;
font-weight: 600;
font-size: 16px;
text-decoration: none;
box-shadow: 0 4px 12px rgba(61, 155, 255, 0.3);
cursor: pointer;
transition: all 0.3s ease;
display: inline-block;
white-space: nowrap;
text-align: center;
min-width: 160px;
}
.download-btn.secondary {
background: linear-gradient(135deg, #6c757d 0%, #495057 100%);
box-shadow: 0 4px 12px rgba(108, 117, 125, 0.3);
}
.download-btn.secondary:hover {
background: linear-gradient(135deg, #5a6268 0%, #3d4349 100%);
box-shadow: 0 6px 16px rgba(108, 117, 125, 0.4);
}
.download-btn:hover {
background: linear-gradient(135deg, #2d8bef 0%, #0055b3 100%);
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(61, 155, 255, 0.4);
}
.download-btn:active {
transform: translateY(0);
box-shadow: 0 2px 8px rgba(61, 155, 255, 0.3);
}
.download-btn:focus {
outline: 2px solid rgba(61, 155, 255, 0.5);
outline-offset: 2px;
}
/* Responsive untuk mobile */
@media (max-width: 768px) {
.download-btn {
bottom: 16px;
right: 16px;
padding: 10px 20px;
font-size: 14px;
}
}
.absolute-view{
background-color: #e6e6e6;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow-y: auto;
z-index: 50;
width: 100%;
}
.certificate_builder_view{
width: 60%;
height: auto;
min-width: 350px;
margin-left: auto;
margin-right: auto;
padding-top: 60px;
}
</style>
@php
$bulan_indonesia = [
1 => 'Januari', 2 => 'Februari', 3 => 'Maret', 4 => 'April',
5 => 'Mei', 6 => 'Juni', 7 => 'Juli', 8 => 'Agustus',
9 => 'September', 10 => 'Oktober', 11 => 'November', 12 => 'Desember'
];
$completion_date = $certificate->created_at;
$timestamp = strtotime($completion_date);
$hari = date('j', $timestamp);
$bulan_angka = (int)date('n', $timestamp);
$tahun = date('Y', $timestamp);
$course_completion_date = $hari . ' ' . $bulan_indonesia[$bulan_angka] . ' ' . $tahun;
$course_duration = $certificate->course->total_duration();
$student_name = $certificate->user->name;
$course_title = $certificate->course->title;
$number_of_lesson = $certificate->course->lessons->count();
$qr_code = $qrcode;
$certificate_id = $certificate->identifier;
$certificate_download_date = date('d M Y');
$course_level = ucfirst($certificate->course->level);
$course_language = ucfirst($certificate->course->language);
$instructor_name = '';
foreach ($certificate->course->instructors() as $instructor) {
$instructor_name .= '<p>' . $instructor->name . '</p>';
}
// --- PERBAIKAN DI SINI (Hapus tanda = yang nyasar) ---
$sections = $certificate->course->sections()->orderBy('sort', 'asc')->get();
// --- PERBAIKAN NAMA VARIABEL ---
// Ubah $section_list menjadi $section_list_html agar sesuai dengan pemanggilan di bawah
$section_list_html = '<ol style="list-style-type: decimal; padding-left: 20px;">';
foreach ($sections as $section) {
$section_list_html .= '<li style="margin-bottom: 5px;">' . $section->title . '</li>';
}
$section_list_html .= '</ol>';
$certificate_builder_content = get_settings('certificate_builder_content');
// Replacements Array (Agar lebih rapi dan bisa dipakai ulang)
$replacements = [
'{course_duration}' => $course_duration,
'{instructor_name}' => $instructor_name,
'{student_name}' => $student_name,
'{course_title}' => $course_title,
'{number_of_lesson}' => $number_of_lesson,
'{qr_code}' => $qr_code,
'{course_completion_date}' => $course_completion_date,
'{certificate_id}' => $certificate_id,
'{certificate_download_date}' => $certificate_download_date,
'{course_level}' => $course_level,
'{course_language}' => $course_language,
];
// Proses Halaman 1
foreach ($replacements as $key => $value) {
$certificate_builder_content = str_replace($key, $value, $certificate_builder_content);
}
// Update Image Src Halaman 1
$newSrc = get_image(get_settings('certificate_template'));
$certificate_builder_content = preg_replace('/(<img[^>]*class=["\']certificate-template["\'][^>]*src=["\'])([^"\']*)(["\'])/i', '${1}' . $newSrc . '${3}', $certificate_builder_content);
// --- PEMROSESAN HALAMAN TAMBAHAN (DETAILS) ---
$certificate_builder_content_details = get_settings('certificate_builder_content_details');
// Proses Halaman 2
foreach ($replacements as $key => $value) {
$certificate_builder_content_details = str_replace($key, $value, $certificate_builder_content_details);
}
// Masukkan Section List (Pastikan variabelnya $section_list_html)
$certificate_builder_content_details = str_replace('{section_list}', $section_list_html, $certificate_builder_content_details);
// Update Image Src Halaman 2
$newSrcDetails = get_image(get_settings('certificate_template_details'));
$certificate_builder_content_details = preg_replace('/(<img[^>]*class=["\']certificate-template-details["\'][^>]*src=["\'])([^"\']*)(["\'])/i', '${1}' . $newSrcDetails . '${3}', $certificate_builder_content_details);
@endphp
{{-- Capture Certificate Wrapper --}}
<div class="captureCertificate" id="captureCertificate">
{{-- Halaman 1 --}}
<div class="certificate-page page-1">
{!! $certificate_builder_content !!}
</div>
{{-- Halaman 2 (Baru) --}}
{{-- Style margin-top hanya visual di web, tidak mempengaruhi PDF split --}}
<div class="certificate-page page-2" style="margin-top: 50px;">
{!! $certificate_builder_content_details !!}
</div>
</div>
{{-- Capture Certificate End --}}
{{-- Preview Certificate --}}
<div class="absolute-view">
<div class="certificate_builder_view" id="certificate_builder_view">
{{-- Tampilkan kedua halaman di preview juga --}}
<div class="certificate-page">
{!! $certificate_builder_content !!}
</div>
<div class="certificate-page" style="margin-top: 20px;">
{!! $certificate_builder_content_details !!}
</div>
</div>
</div>
<div class="download-wrapper">
<!-- <a class="download-btn secondary" href="#"
onclick="setTimeout(() => renderCanvasToImage(), 500); return false;">
{{ get_phrase('Download Image') }}
</a> -->
<a class="download-btn" href="#"
onclick="renderCanvasToPDF(); return false;">
{{ get_phrase('Download Sertificate') }}
</a>
</div>
<script>
"use strict";
$(function() {
// Skrip zoom diperbaiki agar berlaku untuk semua halaman sertifikat
var certificate_builder_view_width = $('.certificate_builder_view').width();
// Ambil modul layout pertama untuk perhitungan rasio
var certificate_layout_module = $('.certificate_builder_view .certificate-layout-module').first().width();
if(certificate_layout_module > 0) {
var zoomScaleValue = ((certificate_builder_view_width / certificate_layout_module) * 100) - 8;
// Terapkan zoom ke SEMUA layout module
$('.certificate_builder_view .certificate-layout-module').css('zoom', zoomScaleValue + '%');
}
});
// Fungsi Gambar (Download PNG) - Hanya mengambil halaman pertama atau gabungan (opsional)
// Disarankan default mengambil halaman utama saja untuk PNG, atau biarkan custom
function renderCanvasToImage() {
// Mengambil elemen halaman pertama saja untuk PNG thumbnail
var elementToCapture = document.querySelector("#captureCertificate .page-1");
var certificate_width = $(elementToCapture).width();
html2canvas(elementToCapture, {
allowTaint: true,
useCORS: true,
width: certificate_width,
scale: 3
}).then(canvas => {
// Logic download existing
var link = document.createElement('a');
link.download = 'certificate.png';
link.href = canvas.toDataURL("image/png");
link.click();
});
}
async function renderCanvasToPDF() {
const pages = document.querySelectorAll("#captureCertificate .certificate-page");
if (pages.length === 0) return;
const pdf = new window.jspdf.jsPDF({
orientation: 'landscape',
unit: 'mm',
format: 'a4'
});
const pageWidth = pdf.internal.pageSize.getWidth(); // 297 mm
const pageHeight = pdf.internal.pageSize.getHeight(); // 210 mm
for (let i = 0; i < pages.length; i++) {
const pageElement = pages[i];
const canvas = await html2canvas(pageElement, {
allowTaint: true,
useCORS: true,
scale: 2, // cukup tajam, jangan kebesaran
backgroundColor: '#ffffff'
});
const imgData = canvas.toDataURL("image/png");
if (i > 0) pdf.addPage();
// 🔥 FULL PAGE TANPA WHITESPACE
pdf.addImage(
imgData,
'PNG',
0,
0,
pageWidth,
pageHeight,
undefined,
'FAST'
);
}
const courseTitle = {!! json_encode($course_title) !!};
const fileName = `Grownesesa Certificate - ${courseTitle}.pdf`;
pdf.save(fileName);
}
</script>
</body>
</html>