File manager - Edit - /home/webtrixia/.trash/hr.html
Back
<!DOCTYPE html> <html lang="bg"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Молби — Webtrixia Hub</title> <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet"> <style> :root{--bg:#f0f0f8;--sur:#fff;--sur2:#f5f5fc;--sur3:#eaeaf5;--brd:rgba(0,0,0,.08);--brd2:rgba(0,0,0,.14); --tx:#1a1a2e;--tx2:#4a4a6a;--tx3:#8888aa;--acc:#6c63ff;--acc2:#a78bfa;--grn:#22c55e;--red:#ef4444; --fn:'DM Sans',sans-serif;--mo:'DM Mono',monospace} *{margin:0;padding:0;box-sizing:border-box} body{font-family:var(--fn);background:var(--bg);color:var(--tx);min-height:100vh;padding:24px 18px} .wrap{max-width:1100px;margin:0 auto} .top{display:flex;justify-content:space-between;align-items:center;margin-bottom:18px;flex-wrap:wrap;gap:10px} h1{font-size:20px;font-weight:600} .sub{font-size:12px;color:var(--tx3);margin-top:2px} .grid{display:grid;grid-template-columns:380px 1fr;gap:18px} @media(max-width:860px){.grid{grid-template-columns:1fr}} .panel{background:var(--sur);border:1px solid var(--brd);border-radius:16px;padding:18px} .ph{font-size:13px;font-weight:600;margin-bottom:12px;display:flex;align-items:center;gap:8px} .tabs{display:flex;gap:6px;margin-bottom:14px;background:var(--sur2);padding:4px;border-radius:10px} .tab{flex:1;text-align:center;padding:8px;border-radius:8px;font-size:12px;font-weight:500;cursor:pointer;color:var(--tx2)} .tab.active{background:var(--sur);color:var(--acc);box-shadow:0 1px 4px rgba(0,0,0,.08)} label{display:block;font-size:11px;color:var(--tx3);text-transform:uppercase;letter-spacing:.06em;margin:10px 0 5px} input,select,textarea{width:100%;background:var(--sur2);border:1px solid var(--brd);border-radius:9px;padding:10px 12px; color:var(--tx);font-family:var(--fn);font-size:13px;outline:none} input:focus,select:focus,textarea:focus{border-color:var(--acc)} textarea{resize:vertical;min-height:70px} .row2{display:grid;grid-template-columns:1fr 1fr;gap:10px} .btn{padding:10px 16px;border-radius:9px;border:none;cursor:pointer;font-family:var(--fn);font-size:13px;font-weight:600;margin-top:14px} .btn.p{background:var(--acc);color:#fff;width:100%} .btn.s{background:var(--sur2);color:var(--tx2);border:1px solid var(--brd)} .doc{background:#fff;border-radius:4px;padding:50px 60px;min-height:600px;font-size:14px;line-height:1.9;color:#111} .doc-toolbar{display:flex;justify-content:flex-end;gap:8px;margin-bottom:12px} .doc h2{font-size:15px;text-align:center;text-transform:uppercase;letter-spacing:.08em;margin-bottom:30px} .doc .to{text-align:right;margin-bottom:26px} .doc .field{border-bottom:1px dotted #888;padding:0 2px;font-weight:600} .doc p{margin-bottom:14px} .doc .sig{display:flex;justify-content:space-between;margin-top:60px} .doc .sig div{font-size:12px;text-align:center} .doc .sig .line{border-top:1px solid #333;margin-top:36px;padding-top:4px;width:170px} .doc .res{margin-top:70px;border-top:1px dashed #aaa;padding-top:16px;font-size:12px;color:#555} table.list{width:100%;border-collapse:collapse;margin-top:8px;font-size:12px} table.list th{text-align:left;padding:8px 10px;color:var(--tx3);font-weight:500;border-bottom:1px solid var(--brd)} table.list td{padding:9px 10px;border-bottom:1px solid var(--brd)} .badge{padding:2px 9px;border-radius:20px;font-size:11px;font-weight:600} .badge.pending{background:rgba(245,158,11,.15);color:#b45309} .badge.approved{background:rgba(34,197,94,.15);color:#15803d} .badge.rejected{background:rgba(239,68,68,.15);color:#b91c1c} .lnk{color:var(--acc);cursor:pointer;font-size:12px;text-decoration:underline} @media print{ body{background:#fff;padding:0} .top,.grid>div:first-child,.doc-toolbar,table.list,.ph,h1,.sub{display:none!important} .grid{display:block} .panel{border:none;padding:0} .doc{padding:20px 10px} } </style> </head> <body> <div class="wrap"> <div class="top"> <div><h1>📄 Молби</h1><div class="sub">Отпуск (платен/неплатен) и предизвестие за напускане</div></div> <div><a href="index.html" class="lnk">← Обратно към Hub</a></div> </div> <div class="grid"> <div class="panel"> <div class="ph">Нова молба</div> <div class="tabs"> <div class="tab active" data-t="leave_paid" onclick="setType(this,'leave_paid')">Платен отпуск</div> <div class="tab" data-t="leave_unpaid" onclick="setType(this,'leave_unpaid')">Неплатен</div> <div class="tab" data-t="resignation" onclick="setType(this,'resignation')">Предизвестие</div> </div> <label>Име на служителя</label> <input id="f_name" placeholder="Име, Фамилия"> <div class="row2"> <div><label>Длъжност</label><input id="f_pos" placeholder="напр. Разработчик"></div> <div><label>ЕГН</label><input id="f_egn" placeholder="**********"></div> </div> <div id="leaveFields"> <div class="row2"> <div><label>От дата</label><input id="f_start" type="date"></div> <div><label>До дата</label><input id="f_end" type="date" onchange="calcDays()"></div> </div> <label>Брой работни дни</label> <input id="f_days" type="number" min="1" value="1"> </div> <div id="resignFields" style="display:none"> <label>Срок на предизвестието (дни)</label> <input id="f_notice" type="number" value="30"> <label>Последен работен ден</label> <input id="f_lastday" type="date"> </div> <label>Основание / бележка (по избор)</label> <textarea id="f_reason" placeholder="напр. на основание чл. 155 от КТ"></textarea> <button class="btn p" onclick="saveRequest()">💾 Запази и генерирай</button> <button class="btn s" style="width:100%" onclick="loadList()">↻ Обнови списъка</button> <div class="ph" style="margin-top:22px">История</div> <table class="list" id="listTbl"><tbody><tr><td>Зарежда…</td></tr></tbody></table> </div> <div class="panel"> <div class="doc-toolbar"> <button class="btn s" onclick="window.print()">🖨️ Принтирай / PDF</button> </div> <div class="doc" id="docView"></div> </div> </div> </div> <script> 'use strict'; var API=(function(){ var saved=localStorage.getItem('wt_api'); if(saved)return saved; var base=window.location.origin+window.location.pathname.replace(/hr\.html$/,'').replace(/\/$/,''); return base+'/api.php'; })(); var CU=(function(){try{var s=sessionStorage.getItem('wt_s');return s?JSON.parse(s):null;}catch(e){return null;}})(); var curType='leave_paid'; async function af(action,method,body,extra){ method=method||'GET';extra=extra||''; try{ var o={method:method,headers:{'Content-Type':'application/json'}}; if(body)o.body=JSON.stringify(body); var r=await fetch(API+'?action='+action+extra,o); var j=await r.json(); return j.ok?j.data:null; }catch(e){console.error(e);return null;} } function setType(el,t){ document.querySelectorAll('.tab').forEach(x=>x.classList.remove('active')); el.classList.add('active'); curType=t; document.getElementById('leaveFields').style.display = t==='resignation' ? 'none':'block'; document.getElementById('resignFields').style.display = t==='resignation' ? 'block':'none'; renderDoc(); } function calcDays(){ var s=document.getElementById('f_start').value, e=document.getElementById('f_end').value; if(s&&e){ var d1=new Date(s), d2=new Date(e); var diff=Math.round((d2-d1)/86400000)+1; if(diff>0) document.getElementById('f_days').value=diff; } renderDoc(); } function fmtDate(s){ if(!s)return '__.__.____'; var d=new Date(s+'T00:00:00'); return String(d.getDate()).padStart(2,'0')+'.'+String(d.getMonth()+1).padStart(2,'0')+'.'+d.getFullYear(); } function collect(){ return { type:curType, employee_name:document.getElementById('f_name').value||'________________', position:document.getElementById('f_pos').value||'', egn:document.getElementById('f_egn').value||'', start_date:document.getElementById('f_start').value||'', end_date:document.getElementById('f_end').value||'', days:document.getElementById('f_days').value||1, notice_days:document.getElementById('f_notice')?document.getElementById('f_notice').value:30, last_work_date:document.getElementById('f_lastday')?document.getElementById('f_lastday').value:'', reason:document.getElementById('f_reason').value||'' }; } function renderDoc(){ var d=collect(); var today=fmtDate(new Date().toISOString().slice(0,10)); var html=''; if(d.type==='leave_paid'||d.type==='leave_unpaid'){ var basis = d.type==='leave_paid' ? 'чл. 155 от Кодекса на труда' : 'чл. 160, ал. 1 от Кодекса на труда'; var kind = d.type==='leave_paid' ? 'платен годишен отпуск' : 'неплатен отпуск'; html += '<h2>Молба за ползване на '+kind+'</h2>'; html += '<div class="to">До Управителя<br>на Уебтриксиа ЕООД</div>'; html += '<p><b>МОЛБА</b></p>'; html += '<p>от <span class="field">'+d.employee_name+'</span>'+(d.position?', на длъжност <span class="field">'+d.position+'</span>':'')+(d.egn?', ЕГН <span class="field">'+d.egn+'</span>':'')+'</p>'; html += '<p>Моля да ми бъде разрешено да ползвам <span class="field">'+d.days+'</span> работни дни '+kind+ ', на основание '+basis+', считано от <span class="field">'+fmtDate(d.start_date)+'</span> до <span class="field">'+fmtDate(d.end_date)+'</span> вкл.</p>'; if(d.reason) html += '<p>Основание/бележка: '+d.reason+'</p>'; html += '<p>Дата: '+today+' г.</p>'; html += '<div class="sig"><div><div class="line">Подпис на служителя</div></div><div><div class="line">Съгласувал / Изготвил</div></div></div>'; html += '<div class="res">Резолюция: ☐ Одобрена ☐ Отказана Дата: __________ Подпис: __________</div>'; } else { html += '<h2>Предизвестие за прекратяване на трудово правоотношение</h2>'; html += '<div class="to">До Управителя<br>на Уебтриксиа ЕООД</div>'; html += '<p><b>ПРЕДИЗВЕСТИЕ</b></p>'; html += '<p>от <span class="field">'+d.employee_name+'</span>'+(d.position?', на длъжност <span class="field">'+d.position+'</span>':'')+(d.egn?', ЕГН <span class="field">'+d.egn+'</span>':'')+'</p>'; html += '<p>На основание чл. 326 от Кодекса на труда, отправям предизвестие за прекратяване на трудовото ми правоотношение '+ 'със срок на предизвестие от <span class="field">'+d.notice_days+'</span> дни.</p>'; html += '<p>Последен работен ден: <span class="field">'+fmtDate(d.last_work_date)+'</span>.</p>'; if(d.reason) html += '<p>Основание/бележка: '+d.reason+'</p>'; html += '<p>Дата: '+today+' г.</p>'; html += '<div class="sig"><div><div class="line">Подпис на служителя</div></div><div><div class="line">Приел / Работодател</div></div></div>'; html += '<div class="res">Резолюция: ☐ Прието Дата на прекратяване: __________ Подпис: __________</div>'; } document.getElementById('docView').innerHTML=html; } ['f_name','f_pos','f_egn','f_start','f_reason','f_notice','f_lastday','f_days'].forEach(id=>{ var el=document.getElementById(id); if(el) el.addEventListener('input',renderDoc); }); async function saveRequest(){ var d=collect(); var r=await af('hr_requests','POST',d); if(r){ alert('Молбата е запазена.'); loadList(); } else alert('Грешка при запис — провери връзката с API (localStorage wt_api).'); } async function loadList(){ var rows=await af('hr_requests'); var tbl=document.getElementById('listTbl'); if(!rows||!rows.length){ tbl.innerHTML='<tr><td style="color:var(--tx3)">Няма записи</td></tr>'; return; } var labels={leave_paid:'Платен отпуск',leave_unpaid:'Неплатен отпуск',resignation:'Предизвестие'}; var html='<thead><tr><th>Служител</th><th>Вид</th><th>Статус</th><th></th></tr></thead><tbody>'; rows.forEach(r=>{ html+='<tr><td>'+r.employee_name+'</td><td>'+(labels[r.type]||r.type)+'</td><td><span class="badge '+r.status+'">'+r.status+'</span></td>'+ '<td style="display:flex;gap:4px">'+ (r.status!=='approved'?'<span class="lnk" style="color:#15803d" onclick="setStatus(\''+r.id+'\',\'approved\')">✓ Одобри</span>':'')+ (r.status!=='rejected'?'<span class="lnk" style="color:#b91c1c" onclick="setStatus(\''+r.id+'\',\'rejected\')">✕ Откажи</span>':'')+ '</td></tr>'; }); html+='</tbody>'; tbl.innerHTML=html; } async function setStatus(id,status){ var who=(CU&&CU.name)?CU.name:'Admin'; var r=await af('hr_request_status','POST',{id:id,status:status,approved_by:who}); if(r!==null){ loadList(); } else alert('Грешка при обновяване на статуса.'); } async function moduleGuard(key,label){ try{ var r=await af('branding_settings'); if(r && (r.license_state==='locked'||r.license_state==='invalid')){ document.body.innerHTML='<div style="max-width:480px;margin:80px auto;text-align:center;font-family:sans-serif;color:#4a4a6a">'+ '<div style="font-size:40px;margin-bottom:12px">🔒</div><h2>Хъбът е заключен</h2>'+ '<p style="margin-top:8px;font-size:13px">'+(r.license_message||'Лицензът не е активен.')+'</p></div>'; return false; } if(r && r.modules_enabled && r.modules_enabled.hasOwnProperty(key) && !r.modules_enabled[key]){ document.body.innerHTML='<div style="max-width:480px;margin:80px auto;text-align:center;font-family:sans-serif;color:#4a4a6a">'+ '<div style="font-size:40px;margin-bottom:12px">🔒</div><h2>'+label+' е изключен</h2>'+ '<p style="margin-top:8px;font-size:13px">Този модул е изключен за тази инсталация. Свържи се с администратора.</p>'+ '<a href="index.html" style="display:inline-block;margin-top:16px;color:#6c63ff">← Обратно към Hub</a></div>'; return false; } }catch(e){} return true; } moduleGuard('hr_requests','Молбите').then(function(ok){ if(ok){ renderDoc(); loadList(); } }); </script> </body> </html>
| ver. 1.4 |
Github
|
.
| PHP 8.2.31 | Generation time: 0.03 |
proxy
|
phpinfo
|
Settings