Hurda Raporu

Hurda raporu tutmamız gerektiğinde, Excel üzerinde hazırlanmış tabloya biraz prestij katarak kurumsal imaj ile form ile imzaya sunmak için hazırlanan çalışmadır. 

(Kod üzerinde "Ctrl+F" ile değişmesini istediğiniz ifadeleri, değiştirip kaydederek html formatında kullanabilirsiniz. Logo için, "logo.jpg" html dosyası ile aynı klasörde olmalıdır. Başlıktaki alanları kodda arayıp birim ve bölümlerinize göre güncelleyebilirsiniz.

Hazır bir metin hazırlandı. Metin üzerine tıklayarak düzenleyebilirsiniz.

Excel üzerinde hazırlanmış bir tabloyu resim olarak kaydedebilir, Teslim alınan bir formun fotoğrafını çekerek resim olarak ekleyebilir. 

Veya tablodan bir liste ekleyebilirsiniz. İmza alanı ekleyebilir, çıkarabilir, başlık, Makamda ekleyebilirsiniz.

Ön izleyebilir, PDF olarak kaydedebilirsiniz.


HTML Kod:
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Hurda Raporu</title>
<style>
    * { margin:0; padding:0; box-sizing:border-box; font-family:'Segoe UI',sans-serif; }
    :root { --primary:#2563eb; --bg:#f3f4f6; --text:#111827; --border:#dbe4ee; }
    body { background:var(--bg); color:var(--text); padding:20px; }
    
    .container { width: 100%; max-width: 100%; margin: auto; } 
    
    .section-box { background:#fff; border:1px solid var(--border); border-radius:12px; margin-bottom:12px; }

    /* Header */
    .main-header { padding:8px 15px; display:flex; justify-content:space-between; align-items:center; box-shadow:0 2px 4px rgba(0,0,0,.05); }
    .header-left { display:flex; align-items:center; gap:15px; }
    .logo-wrapper { width:50px; height:50px; border:1px solid var(--border); border-radius:10px; display:flex; align-items:center; justify-content:center; flex-shrink: 0; cursor: pointer; }
    .logo-wrapper img { width:90%; height:90%; object-fit:contain; }
    .header-center { text-align: center; flex-grow: 1; padding: 0 10px; }
    
    .main-title { font-size:18px; font-weight:800; line-height: 1.1; }
    .subtitle { color:#475569; font-size:13px; font-weight:600; }
    
    .header-right { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
    .dept-text { font-size: 10px; font-weight: 700; color: #64748b; white-space: nowrap; }

    /* Orta Alan - Metin */
    .main-panel { padding:20px; display: flex; flex-direction: column; align-items: center; }
    
    .text-wrapper {
        width: 100%;
        max-width: 210mm; 
        margin: 0 auto 15px auto;
    }

    textarea { 
        width:100%; 
        padding:5px; 
        border: none !important; 
        outline: none !important; 
        background: transparent;
        font-size:16px; 
        resize:none; 
        overflow:hidden;
        min-height: 50px;
        text-align: justify; 
        text-indent: 40px; 
        line-height: 1.5; 
    }
    
    .a4-boundary-indicator {
        font-size: 11px;
        color: #64748b;
        text-align: center;
        margin-bottom: 4px;
        font-weight: 600;
        letter-spacing: 1px;
    }

    .paste-area-wrapper {
        width: 100%;
        max-width: 210mm; 
        margin: 0 auto 15px auto;
        position: relative;
    }

    .paste-area {
        min-height: 40px;
        width: 100%;
        padding: 15px; /* Köşelerin kırpılmasını önlemek için iç boşluk artırıldı */
        border: 1px dashed var(--border);
        border-radius: 8px;
        outline: none;
        overflow-x: auto;
        background: transparent;
        font-size: 14px;
        display: block;
    }
    .paste-area:empty:before {
        content: attr(data-placeholder);
        color: #94a3b8;
        font-style: italic;
        display: block;
        text-align: center;
    }
    .paste-area:focus { border-color: var(--primary); }
    
    /* TABLO DÜZENLEMELERİ (Kırpmaları engelleyen güvenli alan) */
    .paste-area table { 
        border-collapse: collapse !important; 
        width: 100% !important;
        max-width: 100% !important; 
        margin: 0 auto !important; /* Dikey/yatay ortalama */
        background-color: #fff !important; 
        table-layout: auto !important; 
    }
    .paste-area th, .paste-area td { 
        border: 1px solid #94a3b8 !important; 
        padding: 6px 8px !important; 
        word-break: break-word !important; 
        overflow-wrap: anywhere !important; 
        position: relative !important; 
    }
    
    .image-gallery { display:flex; flex-wrap:wrap; justify-content:center; gap:15px; width:100%; margin-top: 10px; }
    .img-thumb { max-width: 100%; height: auto; max-height: 400px; object-fit: contain; border-radius:8px; border:1px solid var(--border); cursor:pointer; }

    .actions { display:flex; gap:10px; justify-content:center; margin-bottom:15px; }
    .btn { border:none; padding:10px 20px; border-radius:10px; font-weight:600; cursor:pointer; color:#fff; transition: opacity 0.2s; }
    .btn:hover { opacity: 0.9; }
    .btn-primary { background:var(--primary); }
    .btn-success { background:#16a34a; }
    
    .btn-light { background: #e5e7eb; color: #374151; }
    .btn-light:hover { background: #d1d5db; }

    /* İmza Alanı */
    .signature-container { margin-bottom: 12px; }
    .signature-controls { display: flex; justify-content: flex-end; gap: 10px; margin-bottom: 10px; }
    
    .signature-grid { display:flex; justify-content:space-evenly; gap: 15px; padding:15px; flex-wrap: wrap; }
    .signature-box { padding:5px; text-align:center; flex: 1; min-width: 180px; max-width: 300px; }
    
    .editable-title { font-size:11px; font-weight:bold; min-height:16px; outline:none; margin-bottom: 2px; }
    .editable-title:focus { border-bottom: 1px dashed var(--primary); }

    .edit-name { border:none; background:transparent; text-align:center; width:100%; font-weight:bold; cursor:pointer; padding:5px; }
    .edit-name:focus { outline:none; border:1px solid var(--primary); border-radius:4px; }
    .sig-line { color:#94a3b8; font-size:11px; margin-top:5px; border-top:1px solid var(--border); display:inline-block; padding:0 30px; }

    /* Yazdırma (Print) Kuralları */
    @media print {
        @page { size: portrait; margin: 1cm; } 
        body { background:#fff; padding:0; }
        .container { max-width: 100% !important; }
        .actions, .btn, .signature-controls, .a4-boundary-indicator { display:none !important; }
        .section-box { border:1px solid #ccc; box-shadow:none; }
        .signature-grid { flex-wrap: nowrap; gap: 10px; }
        .paste-area:empty { display: none !important; }
        
        .paste-area-wrapper { max-width: 100% !important; }
        .paste-area { border: none !important; padding: 5px !important; margin: 10px 0 !important; overflow: visible !important; }
        
        .paste-area table { 
            width: 100% !important; 
            max-width: 100% !important;
            margin: 0 auto !important;
            table-layout: auto !important; 
        }
        .paste-area th, .paste-area td { 
            border: 1px solid #000 !important; 
        }
    }
</style>
</head>
<body>

<div class="container">
    <div class="section-box main-header">
        <div class="header-left">
            <div class="logo-wrapper" id="logoWrapper"><img id="logoImage" src="logo.jpg" alt="Logo" onerror="this.style.display='none'"></div>
            <input type="file" id="logoInput" hidden accept="image/*">
            <div class="subtitle">Helpdesk</div>
        </div>
        <div class="header-center">
            <div class="main-title" contenteditable="true">HURDA RAPORU</div>
        </div>
        <div class="header-right">
            <input type="date" id="tarih" style="border:1px solid var(--border); padding:2px; border-radius:6px; font-size: 11px;">
            <div class="dept-text">MYO</div>
        </div>
    </div>

    <div class="section-box main-panel">
        <div class="text-wrapper">
            <textarea id="metinAlani" rows="1" oninput="autoGrow(this)">Aşağıdaki listede; ekonomik ömrünü doldurmuş, kullanılamaz veya tamir edilemez duruma gelmiş, hurdaya ayrılması gerekli ürünler yer almaktadır.</textarea>
        </div>
        
        <div class="a4-boundary-indicator">--- A4 Sayfa Genişlik Sınırları ---</div>
        <div class="paste-area-wrapper">
            <div id="tableContainer" class="paste-area" contenteditable="true" data-placeholder="Excel veya Word'den kopyaladığınız tabloyu buraya yapıştırabilirsiniz..."></div>
        </div>

        <button class="btn btn-primary" onclick="imageInput.click()">+ Resim Ekle</button>
        <input type="file" id="imageInput" accept="image/*" multiple hidden>
        <div id="imageGallery" class="image-gallery"></div>
    </div>

    <div class="actions">
        <button class="btn btn-success" onclick="window.print()">Yazdır / PDF</button>
    </div>

    <div class="signature-container">
        <div class="signature-controls">
            <button class="btn btn-light" onclick="addSignature()" style="padding: 5px 15px; font-size: 14px;">+ İmza Ekle</button>
            <button class="btn btn-light" onclick="removeSignature()" style="padding: 5px 15px; font-size: 14px;">- İmza Çıkar</button>
        </div>
        
        <div class="section-box signature-grid" id="signatureGrid">
            <div class="signature-box">
                <div class="editable-title" contenteditable="true"></div>
                <input type="text" class="edit-name" value="İsim Soyisim" readonly 
                       ondblclick="this.readOnly=false;" onblur="this.readOnly=true;">
                <div class="sig-line">İmza</div>
            </div>
        </div>
    </div>
</div>

<script>
    tarih.value = new Date().toISOString().split('T')[0];

    function autoGrow(element) {
        element.style.height = "auto";
        element.style.height = (element.scrollHeight) + "px";
    }

    window.addEventListener('DOMContentLoaded', () => {
        autoGrow(document.getElementById('metinAlani'));
    });

    const imageInput = document.getElementById('imageInput');
    const imageGallery = document.getElementById('imageGallery');
    imageInput.addEventListener('change', (e) => {
        for (let file of e.target.files) {
            const reader = new FileReader();
            reader.onload = (ev) => {
                const img = document.createElement('img');
                img.src = ev.target.result;
                img.className = 'img-thumb';
                
                img.onclick = () => {
                    if(confirm('Bu resmi silmek istediğinize emin misiniz?')) img.remove();
                };
                
                imageGallery.appendChild(img);
            };
            reader.readAsDataURL(file);
        }
    });

    logoWrapper.onclick = () => logoInput.click();
    logoInput.onchange = (e) => {
        const reader = new FileReader();
        reader.onload = (ev) => logoImage.src = ev.target.result;
        reader.readAsDataURL(e.target.files[0]);
    };

    function addSignature() {
        const grid = document.getElementById('signatureGrid');
        const box = document.createElement('div');
        box.className = 'signature-box';
        
        box.innerHTML = `
            <div class="editable-title" contenteditable="true"></div>
            <input type="text" class="edit-name" value="İsim Soyisim" readonly 
                   ondblclick="this.readOnly=false;" onblur="this.readOnly=true;">
            <div class="sig-line">İmza</div>
        `;
        grid.appendChild(box);
    }

    function removeSignature() {
        const grid = document.getElementById('signatureGrid');
        if (grid.children.length > 1) {
            grid.removeChild(grid.lastElementChild);
        } else {
            alert('Formda en az bir imza alanı bulunmalıdır.');
        }
    }

    // --- TABLO YAPIŞTIRMA TEMİZLEME VE KENAR KORUMA ---
    const tableContainer = document.getElementById('tableContainer');
    tableContainer.addEventListener('paste', function(e) {
        setTimeout(() => {
            const tables = tableContainer.querySelectorAll('table');
            tables.forEach(table => {
                table.removeAttribute('width');
                table.removeAttribute('cellspacing');
                table.removeAttribute('cellpadding');
                table.removeAttribute('border');
                table.style.width = '100%';
                table.style.maxWidth = '100%';
                table.style.tableLayout = 'auto';
                
                const cells = table.querySelectorAll('th, td');
                cells.forEach(cell => {
                    cell.removeAttribute('width');
                    cell.style.width = '';
                });
            });
        }, 100);
    });

    // --- TABLO BOYUTLANDIRMA SİSTEMİ ---
    let isResizing = false;
    let currentTarget = null;
    let startX, startY, startWidth, startHeight;
    let resizeType = ''; 

    tableContainer.addEventListener('mousemove', function(e) {
        if (isResizing) return;
        
        const table = e.target.closest('table');
        const cell = e.target.closest('td, th');
        
        if (table) {
            const tableRect = table.getBoundingClientRect();
            const isNearTableCorner = (e.clientX > tableRect.right - 20) && (e.clientY > tableRect.bottom - 20);
            
            if (isNearTableCorner) {
                if (cell) cell.style.cursor = 'nwse-resize';
                table.style.cursor = 'nwse-resize';
                return;
            }
        }

        if (cell) {
            const rect = cell.getBoundingClientRect();
            const nearRight = e.clientX > rect.right - 8;
            const nearBottom = e.clientY > rect.bottom - 8;
            
            if (nearRight && nearBottom) cell.style.cursor = 'nwse-resize';
            else if (nearRight) cell.style.cursor = 'col-resize';
            else if (nearBottom) cell.style.cursor = 'row-resize';
            else {
                cell.style.cursor = 'text';
                if (table) table.style.cursor = 'text';
            }
        }
    });

    tableContainer.addEventListener('mousedown', function(e) {
        const table = e.target.closest('table');
        const cell = e.target.closest('td, th');
        
        if (table) {
            const tableRect = table.getBoundingClientRect();
            const isNearTableCorner = (e.clientX > tableRect.right - 20) && (e.clientY > tableRect.bottom - 20);
            
            if (isNearTableCorner) {
                isResizing = true;
                currentTarget = table;
                resizeType = 'table';
                startX = e.clientX;
                startY = e.clientY;
                startWidth = table.offsetWidth;
                startHeight = table.offsetHeight;
                e.preventDefault();
                return;
            }
        }
        
        if (cell) {
            const rect = cell.getBoundingClientRect();
            const nearRight = e.clientX > rect.right - 8;
            const nearBottom = e.clientY > rect.bottom - 8;
            
            if (nearRight || nearBottom) {
                isResizing = true;
                currentTarget = cell;
                startX = e.clientX;
                startY = e.clientY;
                startWidth = currentTarget.offsetWidth;
                startHeight = currentTarget.offsetHeight;
                
                if (nearRight && nearBottom) resizeType = 'both';
                else if (nearRight) resizeType = 'col';
                else resizeType = 'row';
                
                e.preventDefault(); 
            }
        }
    });

    document.addEventListener('mousemove', function(e) {
        if (!isResizing || !currentTarget) return;
        
        const containerInnerWidth = tableContainer.clientWidth - 30; 
        
        if (resizeType === 'table') {
            let newWidth = startWidth + (e.clientX - startX);
            newWidth = Math.min(containerInnerWidth, Math.max(100, newWidth)); 
            
            const newHeight = Math.max(50, startHeight + (e.clientY - startY));
            
            currentTarget.style.width = newWidth + 'px';
            currentTarget.style.minWidth = newWidth + 'px';
            currentTarget.style.maxWidth = containerInnerWidth + 'px'; 
            
            currentTarget.style.height = newHeight + 'px';
            currentTarget.style.minHeight = newHeight + 'px';
        } else {
            if (resizeType === 'col' || resizeType === 'both') {
                let newWidth = startWidth + (e.clientX - startX);
                newWidth = Math.min(containerInnerWidth, Math.max(30, newWidth));
                currentTarget.style.width = newWidth + 'px';
                currentTarget.style.minWidth = newWidth + 'px';
                currentTarget.style.maxWidth = newWidth + 'px'; 
            }
            if (resizeType === 'row' || resizeType === 'both') {
                let newHeight = startHeight + (e.clientY - startY);
                newHeight = Math.max(30, newHeight);
                currentTarget.style.height = newHeight + 'px';
                currentTarget.style.minHeight = newHeight + 'px';
            }
        }
    });

    document.addEventListener('mouseup', function() {
        isResizing = false;
        currentTarget = null;
        resizeType = '';
    });
</script>
</body>
</html>

Kaynaklar:
* Gemini