Files
citrus/resources/views/front/career/verify.blade.php
T

534 lines
24 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.
@extends('layouts.site')
@section('content')
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@500;700;800&family=Inter:wght@300;400;500;600;700&family=Playfair+Display:ital,wght@0,500;0,700;1,400&display=swap" rel="stylesheet">
<div class="bg-slate-100 py-12 no-print">
<div class="container max-w-6xl mx-auto px-4">
<!-- Verification Banner (e-Devlet Style) -->
<div class="bg-emerald-50 border-l-4 border-emerald-500 p-6 rounded-2xl shadow-md mb-8 flex flex-col md:flex-row items-center justify-between gap-6">
<div class="flex items-center gap-4">
<div class="w-12 h-12 rounded-full bg-emerald-500 text-white flex items-center justify-center flex-shrink-0 shadow-lg shadow-emerald-500/20">
<i class="uil uil-shield-check text-2xl"></i>
</div>
<div>
<h3 class="text-lg font-bold text-slate-800">Güvenli Belge Doğrulama</h3>
<p class="text-sm text-slate-500 mt-1">Bu staj sertifikası ve transkripti, Trunçgil Teknopark sistemi üzerinden dijital olarak imzalanıp onaylanmıştır.</p>
</div>
</div>
<div class="flex items-center gap-3 flex-wrap">
<!-- PDF Download Button -->
<button onclick="downloadPDF()" id="pdf-btn" class="px-6 py-3 bg-orange-600 hover:bg-orange-700 text-white font-bold rounded-xl transition-all shadow-lg shadow-orange-500/25 flex items-center gap-2">
<i class="uil uil-file-download text-lg" id="pdf-icon"></i>
<span class="spinner-border spinner-border-sm hidden animate-spin w-4 h-4 border-2 border-white border-t-transparent rounded-full" id="pdf-spinner" role="status"></span>
<span id="pdf-btn-text">PDF Olarak İndir</span>
</button>
<!-- Print Button -->
<button onclick="window.print()" class="px-6 py-3 bg-slate-900 hover:bg-slate-800 text-white font-bold rounded-xl transition-all shadow-md flex items-center gap-2">
<i class="uil uil-print text-lg"></i>
<span>Yazdır</span>
</button>
</div>
</div>
</div>
</div>
<!-- Printable Area -->
<div class="print-container bg-slate-100 py-6 min-h-screen">
<div class="container max-w-6xl mx-auto px-4 pb-20 space-y-12">
<!-- ================= PAGE 1: CERTIFICATE (LANDSCAPE A4) ================= -->
<div class="certificate-container-wrapper overflow-hidden w-full flex justify-center items-start">
<div id="certificate-node" class="certificate-page bg-white rounded-[2rem] shadow-2xl p-12 relative overflow-hidden page-break mx-auto">
<!-- Thin Minimal Orange/Slate Inner Border -->
<div class="absolute inset-6 border border-slate-200/50 rounded-[1.5rem] pointer-events-none z-10"></div>
<div class="absolute inset-[28px] border-2 border-orange-500/15 rounded-[1.3rem] pointer-events-none z-10"></div>
<div class="relative z-10 flex flex-col justify-between h-full min-h-[580px] md:min-h-[540px]">
<!-- Logo & Header -->
<div class="flex justify-between items-center w-full">
<img src="{{ asset('logos/truncgil-yatay.svg') }}" alt="Trunçgil Teknoloji" class="h-12 object-contain">
<div class="text-right">
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest block">Verifikasyon No</span>
<span class="text-xs font-mono font-bold text-slate-800">{{ $application->certificate_code }}</span>
</div>
</div>
<!-- Main Content -->
<div class="text-center my-auto px-4">
<h1 class="font-serif text-3xl md:text-5xl font-extrabold tracking-[0.2em] text-slate-900 uppercase mb-2">Staj Bitirme Sertifikası</h1>
<div class="w-24 h-[3px] bg-orange-500 mx-auto mb-8"></div>
<p class="text-slate-400 text-xs md:text-sm uppercase tracking-wider mb-2">Sayın</p>
<h2 class="font-serif text-2xl md:text-4xl font-extrabold text-slate-900 tracking-wide mb-6">{{ $application->name }}</h2>
<div class="max-w-3xl mx-auto text-slate-700 leading-relaxed text-sm md:text-base space-y-4">
<p>
<strong>{{ \Carbon\Carbon::parse($application->internship_start_date)->format('d.m.Y') }}</strong> -
<strong>{{ \Carbon\Carbon::parse($application->internship_end_date)->format('d.m.Y') }}</strong> tarihleri arasında,
<strong>Trunçgil Teknoloji</strong> bünyesinde gerçekleştirdiği uzaktan staj programını başarıyla tamamlayarak bu belgeyi almaya hak kazanmıştır.
</p>
<p class="text-xs md:text-sm text-slate-500 max-w-2xl mx-auto italic font-serif">
Gösterdiği üstün gayret, sorumluluk bilinci, teknik beceriler ve ekip çalışmasına sağladığı değerli katkılardan dolayı teşekkür eder, profesyonel kariyerinde başarılar dileriz.
</p>
</div>
</div>
<!-- Footer Section (Signatures & Verification QR) -->
<div class="grid grid-cols-3 items-end pt-6 border-t border-slate-100/50">
<!-- Left: QR Code -->
<div class="flex items-center gap-4">
<img src="https://api.qrserver.com/v1/create-qr-code/?size=150x150&data={{ urlencode(route('internship.verify', $application->certificate_code)) }}" alt="QR Code" class="w-28 h-28 border border-slate-200 p-1 rounded-xl bg-white shadow-sm">
<div class="text-left hidden sm:block">
<span class="text-[8px] font-bold text-slate-400 uppercase tracking-wider block">Dijital Doğrulama</span>
<span class="text-[9px] text-slate-500 block">Karekod okutularak belgenin güncelliği e-Devlet stilinde doğrulanabilir.</span>
</div>
</div>
<!-- Middle: Date -->
<div class="text-center">
<span class="text-[9px] text-slate-400 block uppercase tracking-wider">Düzenlenme Tarihi</span>
<span class="text-xs font-bold text-slate-700">{{ \Carbon\Carbon::parse($application->internship_end_date)->format('d.m.Y') }}</span>
</div>
<!-- Right: Authorized Signature -->
<div class="text-right">
<div class="inline-block text-center pr-2">
<!-- Digital Signature Stamp Concept -->
<div class="h-10 flex items-center justify-center mb-1">
<span class="font-sans text-slate-800 font-bold text-sm tracking-wider">Trunçgil Teknoloji</span>
</div>
<span class="font-bold text-slate-800 block text-xs">Onay Makamı</span>
<span class="text-[9px] text-slate-400 block">Staj Koordinatörlüğü</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ================= PAGE 2: TRANSCRIPT (PORTRAIT A4) ================= -->
<div class="transcript-container-wrapper overflow-hidden w-full flex justify-center items-start">
<div id="transcript-node" class="transcript-page bg-white rounded-[2rem] shadow-2xl p-6 md:p-8 relative overflow-hidden mx-auto">
<!-- Thin border decor for transcript -->
<div class="absolute inset-4 border border-slate-100 rounded-[1.5rem] pointer-events-none"></div>
<div class="relative z-10 flex flex-col justify-between h-full text-slate-700">
<div>
<!-- Header -->
<div class="flex justify-between items-center pb-2 border-b border-slate-100 mb-3">
<div>
<h2 class="font-serif font-bold text-slate-900 uppercase transcript-header-title">Staj Akademik Transkripti</h2>
<p class="text-slate-400 tracking-wider uppercase mt-0.5 transcript-header-subtitle">Ve Performans Değerlendirme Raporu</p>
</div>
<img src="{{ asset('logos/truncgil-yatay.svg') }}" alt="Trunçgil Logo" class="h-6 object-contain">
</div>
<!-- Student Info block -->
<div class="bg-slate-50 rounded-xl p-2.5 border border-slate-100 mb-3">
<h3 class="font-bold text-slate-400 uppercase tracking-widest mb-1.5 student-info-title">Öğrenci / Stajyer Bilgileri</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-y-1 gap-x-8 student-info-grid">
<div class="flex justify-between border-b border-slate-200/50 pb-1">
<span class="text-slate-500">Adı Soyadı:</span>
<strong class="text-slate-800">{{ $application->name }}</strong>
</div>
<div class="flex justify-between border-b border-slate-200/50 pb-1">
<span class="text-slate-500">E-Posta Adresi:</span>
<strong class="text-slate-800">{{ $application->email }}</strong>
</div>
<div class="flex justify-between border-b border-slate-200/50 pb-1">
<span class="text-slate-500">Staj Dönemi:</span>
<strong class="text-slate-800">{{ \Carbon\Carbon::parse($application->internship_start_date)->format('d.m.Y') }} - {{ \Carbon\Carbon::parse($application->internship_end_date)->format('d.m.Y') }}</strong>
</div>
<div class="flex justify-between border-b border-slate-200/50 pb-1">
<span class="text-slate-500">Toplam Staj Süresi:</span>
<strong class="text-slate-800">{{ $application->internship_total_days }} İş Günü</strong>
</div>
</div>
</div>
<!-- Dynamic Markdown Content (Transcript and marks) -->
<div class="prose max-w-none text-slate-700 leading-relaxed mb-3">
{!! new \Illuminate\Support\HtmlString(\Illuminate\Support\Str::markdown($application->transcript_markdown ?? '')) !!}
</div>
</div>
<!-- Footer with verification details -->
<div class="w-full flex justify-between items-center pt-2 border-t border-slate-100 gap-4 mt-auto">
<div class="flex items-center gap-3">
<img src="https://api.qrserver.com/v1/create-qr-code/?size=120x120&data={{ urlencode(route('internship.verify', $application->certificate_code)) }}" alt="QR Code" class="w-14 h-14 border border-slate-200 p-0.5 rounded-lg bg-white">
<div>
<span class="font-bold text-slate-400 uppercase tracking-wider block verify-code-label">Güvenli Doğrulama Kodu</span>
<span class="font-mono font-bold text-slate-800 block verify-code">{{ $application->certificate_code }}</span>
</div>
</div>
<div class="text-right text-slate-400 footer-address">
Trunçgil Teknoloji San. ve Tic. Ltd. Şti.<br>
Gaziantep Üniversitesi Teknopark No: 4A
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@push('styles')
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<style>
:root {
/* Global scale factor for transcript page fonts. Adjust this easily (e.g. 1.0, 1.10, 1.20) */
--transcript-font-scale: 1.30;
}
body {
font-family: 'Inter', sans-serif;
}
.font-serif {
font-family: 'Cinzel', 'Playfair Display', Georgia, serif;
}
/* Transcript typography helpers scaled globally */
.transcript-header-title {
font-size: calc(0.875rem * var(--transcript-font-scale)) !important;
}
.transcript-header-subtitle {
font-size: calc(7px * var(--transcript-font-scale)) !important;
}
.student-info-title {
font-size: calc(7.5px * var(--transcript-font-scale)) !important;
}
.student-info-grid {
font-size: calc(8.5px * var(--transcript-font-scale)) !important;
}
.verify-code-label {
font-size: calc(6.5px * var(--transcript-font-scale)) !important;
}
.verify-code {
font-size: calc(9px * var(--transcript-font-scale)) !important;
}
.footer-address {
font-size: calc(7.5px * var(--transcript-font-scale)) !important;
}
/* Screen display aspect styling */
.certificate-page {
width: 1122px;
min-height: 794px;
box-sizing: border-box;
background-image: url('{{ asset("assets/img/cert_bg_futuristic.png") }}');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #ffffff;
}
.transcript-page {
width: 794px;
height: 1122px;
box-sizing: border-box;
}
/* Elegant Markdown Table Styling inside prose (Reduced font sizes & paddings) */
.prose table {
width: 100%;
margin-top: 0.35rem !important;
margin-bottom: 0.35rem !important;
border-collapse: collapse;
text-align: left;
}
.prose th {
font-weight: 700;
padding: 0.2rem 0.35rem !important;
background-color: #f8fafc;
border-bottom: 2px solid #e2e8f0;
color: #1e293b;
font-size: calc(0.45rem * var(--transcript-font-scale)) !important;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.prose td {
padding: 0.2rem 0.35rem !important;
border-bottom: 1px solid #e2e8f0;
color: #334155;
font-size: calc(0.45rem * var(--transcript-font-scale)) !important;
line-height: 1.2 !important;
}
.prose tr:hover {
background-color: #f8fafc;
}
.prose h3 {
font-family: 'Cinzel', serif;
color: #0f172a;
margin-top: 0.5rem !important;
margin-bottom: 0.25rem !important;
border-bottom: 1px solid #e2e8f0;
padding-bottom: 0.15rem;
font-weight: 700;
font-size: calc(0.6rem * var(--transcript-font-scale)) !important;
}
.prose h4 {
color: #1e293b;
margin-top: 0.4rem !important;
margin-bottom: 0.2rem !important;
font-weight: 600;
font-size: calc(0.52rem * var(--transcript-font-scale)) !important;
}
.prose p {
font-size: calc(0.45rem * var(--transcript-font-scale)) !important;
line-height: 1.3 !important;
margin-top: 0.15rem !important;
margin-bottom: 0.2rem !important;
}
.prose ul {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.1rem 0.75rem;
padding-left: 0 !important;
margin-top: 0.25rem !important;
margin-bottom: 0.25rem !important;
list-style-type: none !important;
}
.prose ul li {
font-size: calc(0.45rem * var(--transcript-font-scale)) !important;
line-height: 1.3 !important;
margin: 0 !important;
position: relative;
padding-left: 0.5rem !important;
}
.prose ul li::before {
content: "";
color: #f97316;
position: absolute;
left: 0;
top: 0;
font-weight: bold;
}
.prose blockquote {
border-left: 2px solid #f97316;
padding-left: 0.4rem !important;
font-style: italic;
color: #475569;
margin: 0.4rem 0 !important;
font-size: calc(0.45rem * var(--transcript-font-scale)) !important;
}
/* Print media config for mixed Landscape & Portrait */
@media print {
@page {
margin: 0;
}
@page landscape-page {
size: A4 landscape;
}
@page portrait-page {
size: A4 portrait;
}
body, html {
background-color: #ffffff !important;
margin: 0 !important;
padding: 0 !important;
}
.no-print, header, footer, nav, .site-header, .site-footer {
display: none !important;
}
.print-container {
position: absolute;
left: 0;
top: 0;
width: 100% !important;
padding: 0 !important;
margin: 0 !important;
background-color: transparent !important;
}
.certificate-container-wrapper, .transcript-container-wrapper {
height: auto !important;
overflow: visible !important;
}
.certificate-page {
page: landscape-page;
transform: none !important;
width: 297mm !important;
height: 210mm !important;
min-height: 210mm !important;
margin: 0 !important;
padding: 15mm !important;
box-shadow: none !important;
border: none !important;
box-sizing: border-box !important;
page-break-after: always !important;
break-after: page !important;
background-image: url('{{ asset("assets/img/cert_bg_futuristic.png") }}') !important;
background-size: cover !important;
background-position: center !important;
background-repeat: no-repeat !important;
background-color: #ffffff !important;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
.transcript-page {
page: portrait-page;
transform: none !important;
width: 210mm !important;
height: 297mm !important;
min-height: 297mm !important;
margin: 0 !important;
padding: 10mm !important;
box-shadow: none !important;
border: none !important;
box-sizing: border-box !important;
overflow: hidden !important;
}
}
</style>
@endpush
@push('scripts')
<script>
function scaleDocument(wrapperSelector, nodeSelector, baseWidth, baseHeight) {
const wrapper = document.querySelector(wrapperSelector);
const node = document.querySelector(nodeSelector);
if (!wrapper || !node) return;
const containerWidth = wrapper.offsetWidth;
if (containerWidth < baseWidth) {
const scale = containerWidth / baseWidth;
node.style.transform = `scale(${scale})`;
node.style.transformOrigin = 'top center';
node.style.width = `${baseWidth}px`;
node.style.minWidth = `${baseWidth}px`;
node.style.height = `${baseHeight}px`;
node.style.minHeight = `${baseHeight}px`;
wrapper.style.height = `${baseHeight * scale}px`;
} else {
node.style.transform = '';
node.style.transformOrigin = '';
node.style.width = '';
node.style.minWidth = '';
node.style.height = '';
node.style.minHeight = '';
wrapper.style.height = '';
}
}
function scaleAllDocuments() {
scaleDocument('.certificate-container-wrapper', '#certificate-node', 1122, 794);
scaleDocument('.transcript-container-wrapper', '#transcript-node', 794, 1122);
}
window.addEventListener('resize', scaleAllDocuments);
window.addEventListener('DOMContentLoaded', scaleAllDocuments);
window.addEventListener('load', scaleAllDocuments);
// Immediate and delayed triggers to ensure correct measurement after image & stylesheet loading
scaleAllDocuments();
setTimeout(scaleAllDocuments, 100);
setTimeout(scaleAllDocuments, 500);
setTimeout(scaleAllDocuments, 1500);
async function downloadPDF() {
const btn = document.getElementById('pdf-btn');
const icon = document.getElementById('pdf-icon');
const spinner = document.getElementById('pdf-spinner');
const btnText = document.getElementById('pdf-btn-text');
// Show spinner
btn.disabled = true;
icon.classList.add('hidden');
spinner.classList.remove('hidden');
btnText.textContent = "PDF Hazırlanıyor...";
try {
const { jsPDF } = window.jspdf;
const certEl = document.getElementById('certificate-node');
const transEl = document.getElementById('transcript-node');
// Force elements to normal scale prior to capturing for PDF
const origCertTransform = certEl.style.transform;
const origCertWidth = certEl.style.width;
const origCertHeight = certEl.style.height;
const origTransTransform = transEl.style.transform;
const origTransWidth = transEl.style.width;
const origTransHeight = transEl.style.height;
certEl.style.transform = 'none';
certEl.style.width = '1122px';
certEl.style.height = '794px';
transEl.style.transform = 'none';
transEl.style.width = '794px';
transEl.style.height = '1122px';
// Render Page 1 (Landscape)
const certCanvas = await html2canvas(certEl, {
scale: 2,
useCORS: true,
backgroundColor: '#ffffff',
logging: false
});
const certImgData = certCanvas.toDataURL('image/jpeg', 1.0);
// Initialize landscape A4 document
const pdf = new jsPDF({
orientation: 'landscape',
unit: 'mm',
format: 'a4'
});
pdf.addImage(certImgData, 'JPEG', 0, 0, 297, 210);
// Render Page 2 (Portrait)
const transCanvas = await html2canvas(transEl, {
scale: 2,
useCORS: true,
backgroundColor: '#ffffff',
logging: false
});
const transImgData = transCanvas.toDataURL('image/jpeg', 1.0);
// Calculate exact height using aspect ratio to prevent vertical squishing
const transWidth = 210;
const transHeight = (transCanvas.height * transWidth) / transCanvas.width;
// Add portrait page to PDF
pdf.addPage('a4', 'portrait');
pdf.addImage(transImgData, 'JPEG', 0, 0, transWidth, transHeight);
// Restore styles
certEl.style.transform = origCertTransform;
certEl.style.width = origCertWidth;
certEl.style.height = origCertHeight;
transEl.style.transform = origTransTransform;
transEl.style.width = origTransWidth;
transEl.style.height = origTransHeight;
// Trigger Save File
pdf.save('{{ str()->slug($application->name) }}-staj-belgesi.pdf');
} catch (error) {
console.error("PDF generation failed", error);
alert("PDF oluşturulurken bir hata meydana geldi.");
} finally {
// Restore button
btn.disabled = false;
icon.classList.remove('hidden');
spinner.classList.add('hidden');
btnText.textContent = "PDF Olarak İndir";
}
}
</script>
@endpush
@endsection