Kurumsal yapılarda yıllık izin planlaması, yalnızca personelin izin tarihlerini belirlemekten ibaret değildir. Aynı zamanda operasyonel sürekliliğin korunması, ekip içi iş dağılımının dengelenmesi ve yönetsel görünürlüğün sağlanması açısından kritik bir süreçtir. Ancak bu süreçler çoğu zaman standart Excel tabloları veya klasik Word dokümanları üzerinden yönetildiğinde; veri takibi, görsel düzen, raporlama ve kurumsal sunum açısından yetersiz kalabilmektedir.
Bu ihtiyaçlardan hareketle geliştirilen Yıllık İzin Planlama Formu, izin süreçlerini daha profesyonel, merkezi ve yönetilebilir bir yapıya dönüştürmek amacıyla tasarlanmıştır.
Formun temel amacı;
- Hızlı ve pratik veri girişinin sağlanması,
- Aynı departmanda görev yapan personellerin izin durumlarının toplu olarak görüntülenebilmesi,
- Mevcut çalışan, izinli çalışan ve toplam izin günü bilgilerinin anlık olarak takip edilebilmesi,
- Yönetimsel planlama süreçlerinde operasyonel görünürlüğün artırılması,
- Kurumsal kimliğe uygun, düzenli ve resmi çıktılar alınabilmesi,
- Hazırlanan izin planlarının müdürlükler, koordinatörlükler ve yöneticiler ile prestijli PDF formatında paylaşılabilmesi amacıyla hazırlanmıştır.
Tasarlanan yapı sayesinde yalnızca bir izin listesi oluşturulmamış; aynı zamanda yöneticilerin ekip planlamasını daha kontrollü yönetebileceği, departman bazlı analiz yapabileceği ve süreçleri daha şeffaf takip edebileceği kurumsal bir arayüz ortaya çıkarılmıştır.
Özellikle insan kaynakları, idari işler ve operasyon ekipleri için süreç yönetimini kolaylaştıran bu yapı; modern, okunabilir ve profesyonel tasarımıyla klasik tablo mantığının ötesine geçmektedir. Kurumsal süreçlerde sadece verinin tutulması değil, aynı zamanda doğru sunulması da önemlidir. Bu form, tam olarak bu ihtiyaca cevap vermek üzere geliştirilmiştir.
Kullanımı:
Aşağıdaki html kodu kopyala, Yeni bir not defteri aç, İsim ver. Kopyalanan kodu not defterine yapıştır. Dosya uzantısını html olarak düzenle, kaydet ve çift tıklayarak çalıştır. Web browser üzerinde açılacaktır. (İçerik düzenlemek için, Sağ klik not defteriyle düzenle, yeterlidir.)
Görünüm:
Aşağıda 7 personeli olan bir form yer almaktadır. (Default satır ekli geldiği için 1) yansır. Üst solda bir logo yer almakta, Logonun altında birim, Birim adı, Üst sağda Bölüm adı yer almakta. (Çalıştığınız kuruma ait logonun görülmesini, Helpdesk ve MYO ifadelerinin yerine de Departman ve/veya Müdürlük/Koordinatörlük bilgilerinin yansımasını sağlayabilirsiniz.) Birimde çalışan personelin fotoları, izin kullanacak personelin kayıtlı olacağı satır ve PDF olarak kaydetme/ Yazdırma butonu yer almaktadır.
Bu form bir klasör içinde olmalı, İçerisinde üst menüde görünecek personelin fotoları, kurumunuzun logosu olmalı. (Logo ismi, "logo.jpg" olmalı, Personel fotoları "Per1, Per2...Per7" şeklinde olup, aynı klasörde olmalıdır) Html dosyası bulunduğu yerde, resimler bu adlarla yer alması gerekmektedir.
"Yıllık İzin Planı.html" ismiyle kaydedilen sayfanın üzerinde sağ klik, not defteriyle düzenle ile sayfayı açtığımızda, arama penceresine "ad:" yazarak personel tanımlarının olduğu satıra ulaşabilirsiniz.
Süslü parantezle başlayıp, süslü parantezle biten alanda, Personelin adı ve resmi bulunur. Sonu ".jpg" olan kısım fotolarla eşleşen alandır. ( ad:'Per1' ) olarak başlayan alanlar ise personel isimlerinin düzenleneceği, personelin arttırılıp çıkarılacağı alanlardır.
Burada dikkat edilecek bir diğer husus, Süslü parantez ile başlayıp süslü parantez ile biten son alanda "," olmamasıdır. Son kayıtta olmayacaktır. aşağıda seçilmiş alanı görüyorsunuz, 3. 'nün virgülünden itibaren 7. ye kadar olan alan seçilmiş. o alan silinirse, görünecek personel sayısı 3 tanedir.
Kodda azaltma yapılmasından sonra, 3 personelin kaldığı kod görünümü.
Kodda düzeltme sonrası, html dosyası çalıştırılınca, aşağıdaki gibi görünüme 3 personel yansır.
Personel sayımızı 10 'a çıkarınca aynı şekilde kodu kopyalayıp yapıştırdım. (Per6 - Per10) personel resimleri aynı şekilde düzenledim.
Kod eklendikten sonra, html dosyasının görünümünde Personel sayısı 10 kişiye çıktı. (Per8.jpg, Per.jpg, Per10.jpg) isminde resimleri aynı klasöre koyulmaz ise, aşağıdaki gibi o alanlar boş gözükür.
Kodda yer alan ( ad:'Per1' ) kısımlarına, Personel isimlerini giriyoruz. aşağıda girilmiş hali görülmekte.
Yedi personel için, personel ismi girildikten sonra (düzenleme sonrası, Not defterinde Kaydet demeyi unutmayın. Bir defa yapacağınız işlemdir) Kodu çalıştırdığınızda personel fotoğraflarının altına, İsimlerde yansır.
Personel ismini görünümden mouse la seçip kopyalayıp, (+ Satır ekle) butonu ile yeni satırlar eklenmesi sonrası, Personel için oluşan pencerelere yapıştırdığınızda (Üsteki personel ismi ile satırdaki personel ismi birebir uyum sağladığında) İzinli olacak personelin isminin sol yanına fotoğrafı yansır.
Aşağıda toplam 3 satır ekli, Planlanan İzin tarih aralığı seçilmiş, tarihler arasındaki fark otomatik olarak yansır. İzin takvim aralığında Hafta sonu veya Resmi tatil içermesi durumunda, manuel "Gün" pencere içerisine tıklayarak, İş günü olacak değer olarak güncelleyiniz.
Son bir Adım kaldı. PDF/Yazdır butonuna basma ile, Dijital olarak kaydedip, mail Whatsapp ile iletebilir veya Yazdırabilirsiniz.
PDF olarak Kaydetme, Yazdırma görünümü.HTM KOD:
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Yıllık İzin Planı</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700;800;900&display=swap" rel="stylesheet">
<style>
:root{
--primary:#2563eb;
--primary2:#3b82f6;
--success:#16a34a;
--danger:#dc2626;
--text:#111827;
--muted:#6b7280;
--border:#dbe4f0;
--radius-xl:22px;
--radius-lg:18px;
--shadow-sm:
0 2px 6px rgba(15,23,42,.04);
--shadow:
0 10px 30px rgba(15,23,42,.08);
}
*{
margin:0;
padding:0;
box-sizing:border-box;
}
html,
body{
width:100%;
max-width:100%;
overflow-x:hidden;
}
body{
font-family:'DM Sans',sans-serif;
background:#fff;
color:var(--text);
padding:14px;
}
/* ======================================================
DASHBOARD
====================================================== */
.dashboard{
width:100%;
max-width:100%;
margin:auto;
display:flex;
flex-direction:column;
gap:10px;
overflow:hidden;
}
/* ======================================================
HEADER
====================================================== */
.topbar{
background:#fff;
border:1px solid var(--border);
border-radius:22px;
box-shadow:var(--shadow);
padding:10px 18px;
display:grid;
grid-template-columns:
minmax(220px,1fr)
minmax(320px,2fr)
minmax(220px,1fr);
align-items:center;
gap:12px;
width:100%;
overflow:hidden;
}
.branding{
display:flex;
align-items:center;
gap:14px;
min-width:0;
flex-wrap:wrap;
}
.logo-wrap{
width:60px;
height:60px;
border-radius:16px;
background:#fff;
border:1px solid var(--border);
display:flex;
align-items:center;
justify-content:center;
overflow:hidden;
position:relative;
flex-shrink:0;
}
.logo-wrap img{
width:80%;
height:80%;
object-fit:contain;
}
.logo-upload{
position:absolute;
inset:0;
opacity:0;
cursor:pointer;
}
.title-group{
display:flex;
flex-direction:column;
min-width:0;
}
.title-group h1{
font-size:clamp(16px,2vw,24px);
font-weight:900;
line-height:1.1;
letter-spacing:-.5px;
word-break:break-word;
}
.title-group p{
font-size:clamp(10px,1vw,12px);
color:var(--muted);
margin-top:4px;
word-break:break-word;
}
.header-center{
width:100%;
overflow:hidden;
}
.header-stats{
display:grid;
grid-template-columns:
repeat(3,minmax(90px,1fr));
gap:8px;
width:100%;
}
.header-stat-card{
width:100%;
min-width:0;
padding:10px 6px;
border-radius:16px;
border:1px solid var(--border);
background:
linear-gradient(
180deg,
#fff,
#f8fbff);
text-align:center;
box-shadow:var(--shadow-sm);
}
.header-stat-label{
font-size:clamp(8px,.8vw,10px);
font-weight:900;
text-transform:uppercase;
letter-spacing:.8px;
color:var(--muted);
margin-bottom:4px;
word-break:break-word;
}
.header-stat-value{
font-size:clamp(16px,2vw,24px);
font-weight:900;
}
/* ======================================================
HEADER RIGHT
====================================================== */
.header-right{
font-size:clamp(10px,1vw,15px);
font-weight:900;
color:#000;
display:flex;
align-items:center;
justify-content:flex-end;
text-align:right;
white-space:normal;
word-break:break-word;
width:100%;
padding-right:6px;
line-height:1.2;
}
/* ======================================================
PERSON GRID
====================================================== */
.person-wrapper{
margin-bottom:18px;
overflow:hidden;
}
.person-grid{
display:grid;
grid-template-columns:
repeat(auto-fit,minmax(88px,1fr));
gap:8px;
width:100%;
}
.person-card{
background:#fff;
border:1px solid var(--border);
border-radius:16px;
padding:8px 4px;
text-align:center;
box-shadow:var(--shadow-sm);
min-width:0;
}
.person-photo{
width:48px;
height:48px;
border-radius:14px;
object-fit:cover;
margin:auto;
margin-bottom:6px;
border:3px solid #fff;
box-shadow:var(--shadow-sm);
background:#f3f4f6;
}
.person-name{
font-size:clamp(8px,.8vw,10px);
font-weight:800;
line-height:1.2;
word-break:break-word;
}
/* ======================================================
TABLE
====================================================== */
.table-section{
width:100%;
overflow:hidden;
}
.table-title{
font-size:18px;
font-weight:900;
margin-bottom:12px;
}
.table-wrap{
width:100%;
overflow:hidden;
}
table{
width:100%;
min-width:100%;
table-layout:fixed;
border-collapse:separate;
border-spacing:0 8px;
}
/* ======================================================
COLUMN WIDTHS
====================================================== */
th:nth-child(1),
td:nth-child(1){
width:5%;
}
th:nth-child(2),
td:nth-child(2){
width:18%;
}
th:nth-child(3),
td:nth-child(3){
width:18%;
}
th:nth-child(4),
td:nth-child(4){
width:18%;
}
th:nth-child(5),
td:nth-child(5){
width:7%;
}
th:nth-child(6),
td:nth-child(6){
width:26%;
}
th:nth-child(7),
td:nth-child(7){
width:8%;
}
/* ======================================================
TABLE HEAD
====================================================== */
thead th{
background:
linear-gradient(
180deg,
#f7faff,
#eef4ff);
padding:10px 6px;
font-size:clamp(8px,.9vw,11px);
font-weight:900;
text-transform:uppercase;
letter-spacing:.8px;
color:#1e3a8a;
border-bottom:1px solid var(--border);
text-align:center;
vertical-align:middle;
word-break:break-word;
}
/* ======================================================
TABLE BODY
====================================================== */
tbody tr{
background:#fff;
border-radius:18px;
overflow:hidden;
border:1px solid #e5edf7;
box-shadow:
0 2px 8px rgba(15,23,42,.04);
page-break-inside:avoid;
break-inside:avoid;
}
tbody td{
padding:10px 6px;
vertical-align:middle;
text-align:center;
background:#fff;
}
tbody td:first-child{
border-top-left-radius:18px;
border-bottom-left-radius:18px;
}
tbody td:last-child{
border-top-right-radius:18px;
border-bottom-right-radius:18px;
}
/* ======================================================
FORM
====================================================== */
.row-photo{
width:54px;
height:54px;
border-radius:16px;
overflow:hidden;
border:1px solid var(--border);
margin:auto;
background:#fff;
}
.row-photo img{
width:100%;
height:100%;
object-fit:cover;
}
.table-input,
.table-textarea{
width:100%;
max-width:100%;
border:1px solid var(--border);
background:#f8fbff;
border-radius:14px;
font-family:'DM Sans',sans-serif;
font-size:clamp(9px,.9vw,12px);
outline:none;
transition:.2s;
}
.table-input{
height:48px;
padding:0 10px;
display:flex;
align-items:center;
justify-content:center;
text-align:center;
}
.person-input{
text-align:left !important;
padding-left:10px !important;
font-weight:700;
}
.days-input{
font-size:clamp(10px,1vw,14px);
font-weight:900;
text-align:center !important;
padding:0 !important;
display:flex;
align-items:center;
justify-content:center;
}
.table-input:focus,
.table-textarea:focus{
border-color:#93c5fd;
background:#fff;
box-shadow:
0 0 0 4px rgba(37,99,235,.08);
}
.table-textarea{
height:48px;
min-height:48px;
max-height:48px;
resize:none;
padding:10px;
line-height:22px;
text-align:left;
overflow:hidden;
display:flex;
align-items:center;
justify-content:flex-start;
}
/* ======================================================
DATE AREA
====================================================== */
.date-wrap{
display:flex;
align-items:center;
justify-content:center;
gap:6px;
width:100%;
flex-direction:row;
}
.date-input{
order:1;
width:38px;
height:38px;
border:none;
border-radius:12px;
background:
linear-gradient(
135deg,
#dbeafe,
#bfdbfe);
cursor:pointer;
appearance:none;
-webkit-appearance:none;
color:transparent;
flex-shrink:0;
box-shadow:
0 2px 6px rgba(59,130,246,.18);
}
.start-text,
.end-text{
order:2;
flex:1;
min-width:0;
}
.date-input::-webkit-calendar-picker-indicator{
opacity:1;
cursor:pointer;
width:18px;
height:18px;
}
/* ======================================================
BUTTONS
====================================================== */
.table-actions{
display:flex;
flex-wrap:wrap;
justify-content:flex-end;
gap:8px;
margin-top:14px;
width:100%;
}
.btn{
height:40px;
padding:0 10px;
border:none;
border-radius:14px;
font-size:clamp(9px,.9vw,12px);
font-weight:800;
font-family:'DM Sans',sans-serif;
cursor:pointer;
color:#fff;
transition:.2s;
white-space:nowrap;
}
.btn:hover{
transform:translateY(-1px);
}
.btn-success{
background:
linear-gradient(
135deg,
#16a34a,
#22c55e);
}
.btn-danger{
background:
linear-gradient(
135deg,
#dc2626,
#ef4444);
}
/* ======================================================
PRINT
====================================================== */
@media print{
@page{
size:A4 landscape;
margin:8mm;
}
html,
body{
width:100% !important;
overflow:hidden !important;
zoom:.82;
-webkit-print-color-adjust:exact;
print-color-adjust:exact;
}
body{
padding:0;
}
.no-print{
display:none !important;
}
.print-hidden-row{
display:none !important;
}
.dashboard{
width:100% !important;
max-width:100% !important;
}
.topbar{
grid-template-columns:
1fr 1.2fr 1fr !important;
gap:10px !important;
align-items:center !important;
}
/* ======================================================
PRINT HEADER RIGHT
====================================================== */
.header-right{
display:flex !important;
align-items:center !important;
justify-content:flex-end !important;
text-align:right !important;
width:100% !important;
padding-right:6px !important;
font-size:12px !important;
font-weight:900 !important;
color:#000 !important;
white-space:normal !important;
line-height:1.2 !important;
}
.header-stats{
grid-template-columns:
repeat(3,1fr) !important;
}
table{
width:100% !important;
min-width:100% !important;
table-layout:fixed !important;
border-spacing:0 8px !important;
}
thead{
display:table-header-group;
}
tbody{
display:table-row-group;
}
tr{
page-break-inside:avoid !important;
break-inside:avoid !important;
}
thead th{
font-size:9px !important;
padding:8px 4px !important;
}
tbody td{
padding:8px 4px !important;
}
.table-input,
.table-textarea{
font-size:10px !important;
height:42px !important;
min-height:42px !important;
max-height:42px !important;
}
.date-wrap{
flex-direction:row !important;
gap:4px !important;
}
.date-input{
width:30px !important;
height:30px !important;
}
.btn{
display:none !important;
}
}
/* ======================================================
TABLET
====================================================== */
@media(max-width:900px){
.topbar{
grid-template-columns:1fr;
}
.header-right{
text-align:left;
justify-content:flex-start;
}
.header-stats{
grid-template-columns:
repeat(3,1fr);
}
.date-wrap{
flex-direction:row !important;
gap:4px;
}
.date-input{
width:34px;
height:34px;
}
}
/* ======================================================
MOBILE
====================================================== */
@media(max-width:640px){
body{
padding:8px;
}
.topbar{
padding:10px;
}
.header-stat-card{
padding:8px 4px;
}
.person-grid{
grid-template-columns:
repeat(auto-fit,minmax(72px,1fr));
}
.table-actions{
justify-content:center;
}
.btn{
width:100%;
}
}
</style>
</head>
<body>
<div class="dashboard">
<section class="topbar">
<div class="branding">
<div class="logo-wrap">
<img id="logoPreview" src="logo.jpg">
<input
type="file"
class="logo-upload"
id="logoInput"
accept="image/*">
</div>
<div class="title-group">
<h1>
YILLIK İZİN PLANI
</h1>
<p>
Helpdesk
</p>
</div>
</div>
<div class="header-center">
<div class="header-stats">
<div class="header-stat-card">
<div class="header-stat-label">
Aktif Personel
</div>
<div class="header-stat-value" id="personCount">
0
</div>
</div>
<div class="header-stat-card">
<div class="header-stat-label">
Toplam İzin Kaydı
</div>
<div class="header-stat-value" id="rowCount">
0
</div>
</div>
<div class="header-stat-card">
<div class="header-stat-label">
Toplam İzin Günü
</div>
<div class="header-stat-value" id="totalDays">
0
</div>
</div>
</div>
</div>
<div class="header-right">
MYO
</div>
</section>
<section class="person-wrapper">
<div
class="person-grid"
id="personGrid"></div>
</section>
<section class="table-section">
<div class="table-title">
PERSONEL İZİN RAPORU
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Foto</th>
<th>Personel</th>
<th>Başlangıç</th>
<th>Bitiş</th>
<th>Gün</th>
<th>Açıklama</th>
<th class="no-print">İşlem</th>
</tr>
</thead>
<tbody id="tbody"></tbody>
</table>
</div>
<div class="table-actions no-print">
<button
class="btn btn-success"
id="addRowBtn">
+ Satır Ekle
</button>
<button
class="btn btn-danger"
onclick="window.print()">
PDF / Yazdır
</button>
</div>
</section>
</div>
<script>
const state = {
persons:[
{
ad:'Per1',
foto:'Per1.jpg'
},
{
ad:'Per2',
foto:'Per2.jpg'
},
{
ad:'Per3',
foto:'Per3.jpg'
},
{
ad:'Per4',
foto:'Per4.jpg'
},
{
ad:'Per5',
foto:'Per5.jpg'
},
{
ad:'Per6',
foto:'Per6.jpg'
},
{
ad:'Muhammed Yusuf OLGUN',
foto:'Per7.jpg'
}
]
};
const personGrid =
document.getElementById('personGrid');
const tbody =
document.getElementById('tbody');
function init(){
renderPersons();
addRow();
updateStats();
bindEvents();
}
function renderPersons(){
personGrid.innerHTML='';
state.persons.forEach(person=>{
const card=document.createElement('div');
card.className='person-card';
card.innerHTML=`
<img
src="${person.foto}"
class="person-photo">
<div class="person-name">
${person.ad}
</div>
`;
personGrid.appendChild(card);
});
updateStats();
}
function formatDate(val){
if(!val) return '';
return new Date(val)
.toLocaleDateString(
'tr-TR',
{
day:'2-digit',
month:'2-digit',
year:'numeric',
weekday:'long'
})
.replace(',',' -');
}
function calculateDateDifference(start,end){
if(!start || !end) return '';
const startDate =
new Date(start);
const endDate =
new Date(end);
const diff =
(endDate - startDate)
/
(1000*60*60*24)
+1;
return diff > 0 ? diff : '';
}
function addRow(data={}){
const tr=document.createElement('tr');
tr.innerHTML=`
<td>
<div class="row-photo">
${data.photo ? `<img src="${data.photo}">` : ''}
</div>
</td>
<td>
<input
class="table-input person-input"
value="${data.name || ''}">
</td>
<td>
<div class="date-wrap">
<input
type="date"
class="date-input start-date"
value="${data.startRaw || ''}">
<input
class="table-input start-text"
readonly
value="${data.start || ''}">
</div>
</td>
<td>
<div class="date-wrap">
<input
type="date"
class="date-input end-date"
value="${data.endRaw || ''}">
<input
class="table-input end-text"
readonly
value="${data.end || ''}">
</div>
</td>
<td>
<input
class="table-input days-input"
value="${data.days || ''}">
</td>
<td>
<textarea
class="table-textarea"
placeholder="Açıklama...">${data.note || ''}</textarea>
</td>
<td class="no-print">
<button
class="btn btn-danger delete-btn">
Sil
</button>
</td>
`;
tbody.appendChild(tr);
bindRow(tr);
updateStats();
}
function bindRow(tr){
const startDate=
tr.querySelector('.start-date');
const endDate=
tr.querySelector('.end-date');
const startText=
tr.querySelector('.start-text');
const endText=
tr.querySelector('.end-text');
const daysInput=
tr.querySelector('.days-input');
const personInput=
tr.querySelector('.person-input');
const textarea=
tr.querySelector('.table-textarea');
const photoWrap=
tr.querySelector('.row-photo');
function refreshDays(){
if(
startDate.value &&
endDate.value
){
if(
new Date(endDate.value)
<
new Date(startDate.value)
){
alert(
'Bitiş tarihi başlangıç tarihinden küçük olamaz.'
);
endDate.value='';
endText.value='';
daysInput.value='';
updateStats();
return;
}
daysInput.value =
calculateDateDifference(
startDate.value,
endDate.value
);
updateStats();
}
}
startDate.addEventListener(
'change',
()=>{
startText.value =
formatDate(startDate.value);
refreshDays();
});
endDate.addEventListener(
'change',
()=>{
endText.value =
formatDate(endDate.value);
refreshDays();
});
daysInput.addEventListener(
'input',
updateStats
);
personInput.addEventListener(
'input',
()=>{
const value=
personInput.value
.toUpperCase()
.trim();
photoWrap.innerHTML='';
state.persons.forEach(p=>{
if(
p.ad.toUpperCase()
===
value
){
photoWrap.innerHTML=
`<img src="${p.foto}">`;
}
});
if(
textarea.value.trim()===''
){
textarea.value =
personInput.value
? 'Yıllık İzin'
: '';
}
});
tr.querySelector('.delete-btn')
.addEventListener(
'click',
()=>{
tr.remove();
if(
document.querySelectorAll('#tbody tr')
.length===0
){
addRow();
}
updateStats();
});
}
function updateStats(){
const rows=
document.querySelectorAll('#tbody tr');
let totalDays=0;
rows.forEach(r=>{
const val=Number(
r.querySelector('.days-input')
?.value || 0
);
totalDays += val;
});
document.getElementById(
'personCount'
).innerText=
state.persons.length;
document.getElementById(
'rowCount'
).innerText=
rows.length;
document.getElementById(
'totalDays'
).innerText=
totalDays;
}
window.addEventListener(
'beforeprint',
()=>{
const rows =
document.querySelectorAll('#tbody tr');
rows.forEach(row=>{
const person =
row.querySelector('.person-input')?.value.trim();
const start =
row.querySelector('.start-date')?.value.trim();
const end =
row.querySelector('.end-date')?.value.trim();
const days =
row.querySelector('.days-input')?.value.trim();
const note =
row.querySelector('.table-textarea')?.value.trim();
const isEmpty =
!person &&
!start &&
!end &&
!days &&
!note;
if(isEmpty){
row.classList.add(
'print-hidden-row'
);
}else{
row.classList.remove(
'print-hidden-row'
);
}
});
});
function bindEvents(){
const logoInput =
document.getElementById(
'logoInput'
);
const logoPreview =
document.getElementById(
'logoPreview'
);
logoInput.addEventListener(
'change',
e=>{
const file =
e.target.files[0];
if(file){
logoPreview.src =
URL.createObjectURL(file);
}
});
document.getElementById(
'addRowBtn'
)
.addEventListener(
'click',
()=>addRow()
);
}
init();
</script>
</body>
</html>











