Skip to content

Minijob finder #32

Description

@bohlkaukai-alt
<title>MiniJob Finder</title>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&family=Poppins:wght@600;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

<style>
    :root {
        --primary-blue: #1565C0; --accent-orange: #FF9800; --success: #4CAF50;
        --danger: #F44336; --star: #FFC107; --pinned: #E3F2FD;
        --radius: 16px; --radius-sm: 10px; --reserved: #FFF3E0;
    }

    [data-theme="light"] {
        --bg: #F5F5F5; --surface: #FFFFFF; --card: #FFFFFF;
        --text: #333333; --text-secondary: #666666; --border: #E0E0E0;
    }

    [data-theme="dark"] {
        --bg: #121212; --surface: #1E1E1E; --card: #2D2D2D;
        --text: #E0E0E0; --text-secondary: #AAAAAA; --border: #333333;
        --pinned: #1A237E; --reserved: #3E2723;
    }

    * { margin: 0; padding: 0; box-sizing: border-box; }

    body {
        font-family: 'Nunito', sans-serif; background: var(--bg); color: var(--text);
        min-height: 100vh; -webkit-tap-highlight-color: transparent; overscroll-behavior: none;
    }

    #app { max-width: 480px; margin: 0 auto; min-height: 100vh; display: flex; flex-direction: column; }

    .app-header {
        background: var(--surface); padding: 10px 16px; display: flex; align-items: center;
        gap: 10px; border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; min-height: 50px;
    }

    .app-header h1 {
        font-family: 'Poppins', sans-serif; font-size: 19px; color: var(--primary-blue);
        display: flex; align-items: center; gap: 8px; flex: 1;
    }

    .back-arrow {
        display: flex; align-items: center; justify-content: center; width: 38px; height: 38px;
        border: none; background: none; color: var(--text); cursor: pointer; border-radius: 50%;
        font-size: 26px; flex-shrink: 0; transition: all 0.2s;
    }
    .back-arrow:hover { background: var(--border); }
    .back-arrow:active { transform: scale(0.9); }

    .header-title {
        font-size: 17px; font-weight: 700; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }

    .location-badge {
        display: flex; align-items: center; gap: 4px; background: var(--bg); padding: 6px 10px;
        border-radius: 20px; font-size: 11px; font-weight: 600; cursor: pointer;
        border: 2px solid var(--border); color: var(--text); max-width: 110px;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex-shrink: 0;
    }

    .main-content { flex: 1; overflow-y: auto; padding-bottom: 70px; }

    .bottom-nav {
        position: fixed; bottom: 0; left: 50%; transform: translateX(-50%); max-width: 480px; width: 100%;
        background: var(--surface); border-top: 1px solid var(--border); display: flex;
        justify-content: space-around; padding: 6px 0; z-index: 100;
    }

    .nav-item {
        display: flex; flex-direction: column; align-items: center; gap: 2px; cursor: pointer;
        padding: 6px 12px; border: none; background: none; color: var(--text-secondary);
        font-family: 'Nunito', sans-serif; font-size: 10px; font-weight: 600; transition: all 0.2s;
    }
    .nav-item.active { color: var(--primary-blue); }
    .nav-item .material-icons { font-size: 22px; }

    .card {
        background: var(--card); border-radius: var(--radius); padding: 14px; margin: 8px 14px;
        box-shadow: 0 2px 8px rgba(0,0,0,0.08); border: 1px solid var(--border); transition: all 0.15s;
    }
    .card:active { transform: scale(0.98); }

    .job-card.reserved {
        border-left: 4px solid var(--accent-orange);
        background: var(--reserved);
    }

    .job-card.reserved::after {
        content: '🔒 RESERVIERT';
        position: absolute;
        top: 8px;
        right: 40px;
        background: var(--accent-orange);
        color: white;
        padding: 3px 8px;
        border-radius: 10px;
        font-size: 10px;
        font-weight: 700;
    }

    .job-category {
        background: rgba(255, 152, 0, 0.15); color: var(--accent-orange);
        padding: 4px 10px; border-radius: 20px; font-size: 11px; font-weight: 700; white-space: nowrap;
    }

    .distance-badge {
        background: rgba(76, 175, 80, 0.15); color: var(--success);
        padding: 4px 10px; border-radius: 20px; font-size: 11px; font-weight: 700;
        display: flex; align-items: center; gap: 3px;
    }

    .status-badge {
        padding: 4px 10px; border-radius: 20px; font-size: 11px; font-weight: 700;
        display: inline-block;
    }
    .status-badge.offen { background: rgba(76,175,80,0.15); color: var(--success); }
    .status-badge.reserviert { background: rgba(255,152,0,0.15); color: var(--accent-orange); }
    .status-badge.vergeben { background: rgba(33,150,243,0.15); color: #2196F3; }
    .status-badge.erledigt { background: rgba(156,39,176,0.15); color: #9C27B0; }

    .btn {
        padding: 11px 20px; border-radius: 25px; border: none; cursor: pointer; font-size: 14px;
        font-weight: 700; font-family: 'Nunito', sans-serif; display: flex; align-items: center;
        justify-content: center; gap: 6px; transition: all 0.15s;
    }
    .btn:active { transform: scale(0.96); }
    .btn-accent { background: var(--accent-orange); color: white; width: 100%; }
    .btn-primary { background: var(--primary-blue); color: white; width: 100%; }
    .btn-outline { background: transparent; border: 2px solid var(--primary-blue); color: var(--primary-blue); width: 100%; }
    .btn-danger { background: var(--danger); color: white; width: 100%; }
    .btn-reserve { background: var(--accent-orange); color: white; width: 100%; }
    .btn-unreserve { background: #795548; color: white; width: 100%; }

    .form-input, .form-textarea, select.form-input {
        width: 100%; padding: 11px 14px; border-radius: var(--radius-sm); border: 2px solid var(--border);
        background: var(--card); color: var(--text); font-size: 14px; font-family: 'Nunito', sans-serif; outline: none;
    }
    .form-input:focus, .form-textarea:focus { border-color: var(--primary-blue); }
    .form-textarea { min-height: 90px; resize: vertical; }
    .form-group { margin-bottom: 14px; }
    .form-group label { display: block; margin-bottom: 5px; font-weight: 600; font-size: 13px; }

    .filter-scroll { display: flex; gap: 8px; overflow-x: auto; padding: 10px 14px; scrollbar-width: none; }
    .filter-scroll::-webkit-scrollbar { display: none; }

    .filter-chip {
        padding: 7px 14px; border-radius: 20px; border: 2px solid var(--border); background: var(--card);
        color: var(--text); cursor: pointer; white-space: nowrap; font-size: 12px; font-weight: 600;
        transition: all 0.2s; flex-shrink: 0;
    }
    .filter-chip.active { background: var(--accent-orange); color: white; border-color: var(--accent-orange); }

    .search-input {
        width: 100%; padding: 10px 14px; border-radius: var(--radius-sm); border: 2px solid var(--border);
        background: var(--card); color: var(--text); font-size: 14px; outline: none; margin: 10px 14px; width: calc(100% - 28px);
    }

    .profile-avatar {
        width: 70px; height: 70px; border-radius: 50%; background: var(--primary-blue);
        margin: 0 auto 8px; display: flex; align-items: center; justify-content: center;
        font-size: 28px; color: white; font-weight: 700; overflow: hidden;
    }
    .profile-avatar img { width: 100%; height: 100%; object-fit: cover; }

    .chat-bubble {
        max-width: 78%; padding: 10px 14px; border-radius: 18px; margin: 3px 0;
        font-size: 14px; word-wrap: break-word;
    }
    .chat-bubble.sent { background: var(--primary-blue); color: white; align-self: flex-end; border-bottom-right-radius: 4px; }
    .chat-bubble.received { background: var(--border); color: var(--text); align-self: flex-start; border-bottom-left-radius: 4px; }

    .toast {
        position: fixed; bottom: 85px; left: 50%; transform: translateX(-50%); background: #333;
        color: white; padding: 10px 20px; border-radius: 25px; font-size: 13px; font-weight: 600;
        z-index: 300; text-align: center; max-width: 90%;
    }

    .empty-state { text-align: center; padding: 35px 18px; color: var(--text-secondary); }
    .empty-state .material-icons { font-size: 52px; color: #9E9E9E; margin-bottom: 10px; }
    .hidden { display: none !important; }

    .settings-item {
        display: flex; align-items: center; justify-content: space-between;
        padding: 14px 0; border-bottom: 1px solid var(--border); cursor: pointer;
    }
    .settings-item-left { display: flex; align-items: center; gap: 8px; }

    .toggle-switch { width: 48px; height: 26px; border-radius: 13px; background: var(--border); cursor: pointer; transition: background 0.3s; }
    .toggle-switch.active { background: var(--primary-blue); }
    .toggle-switch::after { content: ''; display: block; width: 20px; height: 20px; border-radius: 50%; background: white; margin: 3px; transition: transform 0.3s; }
    .toggle-switch.active::after { transform: translateX(22px); }

    .modal-overlay {
        position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6);
        z-index: 200; display: flex; align-items: center; justify-content: center; padding: 20px;
    }
    .modal-content {
        background: var(--surface); border-radius: var(--radius); padding: 24px;
        width: 100%; max-width: 400px; max-height: 80vh; overflow-y: auto;
    }
</style>
<div id="app">
    <div id="app-header-container"></div>
    <div class="main-content" id="main-content"></div>

    <nav class="bottom-nav hidden" id="bottom-nav">
        <button class="nav-item active" data-page="jobs" onclick="navigateTo('jobs')">
            <span class="material-icons">home</span>Start
        </button>
        <button class="nav-item" data-page="create" onclick="navigateTo('create')">
            <span class="material-icons">add_circle_outline</span>Neu
        </button>
        <button class="nav-item" data-page="chats" onclick="navigateTo('chats')">
            <span class="material-icons">chat_bubble_outline</span>Chat
        </button>
        <button class="nav-item" data-page="profile" onclick="navigateTo('profile')">
            <span class="material-icons">person_outline</span>Profil
        </button>
    </nav>
</div>

<input type="file" id="image-upload" accept="image/*" style="display:none" onchange="handleImageUpload(event)">

<script>
    // ==================== DATENBANK MIT STORAGE-EVENT ====================
    const DB = {
        _users: JSON.parse(localStorage.getItem('mf_users') || '{}'),
        _jobs: JSON.parse(localStorage.getItem('mf_jobs') || '[]'),
        _chats: JSON.parse(localStorage.getItem('mf_chats') || '[]'),
        _messages: JSON.parse(localStorage.getItem('mf_messages') || '{}'),
        _applications: JSON.parse(localStorage.getItem('mf_applications') || '[]'),

        get users() { return this._users; },
        set users(v) { this._users = v; this.save(); },
        get jobs() { return this._jobs; },
        set jobs(v) { this._jobs = v; this.save(); },
        get chats() { return this._chats; },
        set chats(v) { this._chats = v; this.save(); },
        get messages() { return this._messages; },
        set messages(v) { this._messages = v; this.save(); },
        get applications() { return this._applications; },
        set applications(v) { this._applications = v; this.save(); },

        save() {
            localStorage.setItem('mf_users', JSON.stringify(this._users));
            localStorage.setItem('mf_jobs', JSON.stringify(this._jobs));
            localStorage.setItem('mf_chats', JSON.stringify(this._chats));
            localStorage.setItem('mf_messages', JSON.stringify(this._messages));
            localStorage.setItem('mf_applications', JSON.stringify(this._applications));
            // Trigger für andere Tabs
            localStorage.setItem('mf_lastUpdate', Date.now().toString());
        },

        reload() {
            this._users = JSON.parse(localStorage.getItem('mf_users') || '{}');
            this._jobs = JSON.parse(localStorage.getItem('mf_jobs') || '[]');
            this._chats = JSON.parse(localStorage.getItem('mf_chats') || '[]');
            this._messages = JSON.parse(localStorage.getItem('mf_messages') || '{}');
            this._applications = JSON.parse(localStorage.getItem('mf_applications') || '[]');
        }
    };

    // ==================== LIVE-UPDATE ZWISCHEN TABS ====================
    window.addEventListener('storage', function(e) {
        if (e.key === 'mf_lastUpdate') {
            console.log('🔄 Änderung erkannt - aktualisiere...');
            DB.reload();
            // Aktuelle Seite neu rendern
            if (currentUser && currentPage) {
                switch(currentPage) {
                    case 'jobs': renderJobs(); break;
                    case 'chats': showChatsScreen(); break;
                    case 'job-detail': if (currentPageData) showJobDetailScreen(currentPageData); break;
                }
            }
        }
    });

    // ==================== POLLING FÜR LIVE-UPDATES ====================
    let lastUpdateCheck = Date.now();
    setInterval(() => {
        const currentUpdate = parseInt(localStorage.getItem('mf_lastUpdate') || '0');
        if (currentUpdate > lastUpdateCheck) {
            lastUpdateCheck = currentUpdate;
            DB.reload();
            if (currentUser && currentPage === 'jobs') {
                renderJobs();
            }
        }
    }, 2000); // Alle 2 Sekunden prüfen

    const FEEDBACK_EMAIL = atob('Ym9obGthdWthaUBnbWFpbC5jb20=');

    let userLocation = JSON.parse(localStorage.getItem('mf_location') || 'null');
    let userCoordinates = null;
    let navigationHistory = [];
    let currentUser = null;
    let selectedCategory = null;
    let radiusFilter = parseInt(localStorage.getItem('mf_radius') || '50');
    let currentPage = '';
    let currentPageData = null;
    let pinnedChats = JSON.parse(localStorage.getItem('mf_pinnedChats') || '{}');

    const categories = ['Alle','Nachhilfe','Hundesitting','Babysitting','Gartenarbeit','Einkaufen helfen','Computerhilfe','Haushaltshilfe','Sonstiges'];
    const radiusOptions = [5,10,20,30,50,75,100,200];

    // ==================== INIT ====================
    function init() {
        if (userLocation) userCoordinates = { lat: userLocation.lat, lng: userLocation.lng };
        else {
            userLocation = { lat: 51.89, lng: 10.17, name: 'Seesen' };
            userCoordinates = { lat: 51.89, lng: 10.17 };
            localStorage.setItem('mf_location', JSON.stringify(userLocation));
        }
        if (Object.keys(DB.users).length === 0) initDemoData();
        const savedUser = JSON.parse(localStorage.getItem('mf_currentUser') || 'null');
        if (savedUser && DB.users[savedUser.email]) {
            currentUser = DB.users[savedUser.email];
            document.getElementById('bottom-nav').classList.remove('hidden');
            navigateTo('jobs');
        } else showLoginScreen();
    }

    function initDemoData() {
        DB._users = {
            'max@test.de': { uid: 'user1', name: 'Max (16)', email: 'max@test.de', password: '123456', age: 16, photoURL: '', bio: 'Schüler', ratingSum: 23, ratingCount: 5, completedJobs: 12, blockedUsers: [], createdAt: new Date().toISOString() },
            'lisa@test.de': { uid: 'user2', name: 'Lisa (15)', email: 'lisa@test.de', password: '123456', age: 15, photoURL: '', bio: 'Mag Tiere', ratingSum: 18, ratingCount: 4, completedJobs: 8, blockedUsers: [], createdAt: new Date().toISOString() },
            'herr-mueller@test.de': { uid: 'user3', name: 'Herr Müller (45)', email: 'herr-mueller@test.de', password: '123456', age: 45, photoURL: '', bio: 'Nachhilfe & Garten', ratingSum: 45, ratingCount: 9, completedJobs: 25, blockedUsers: [], createdAt: new Date().toISOString() }
        };
        DB._jobs = [
            { id: 'job1', title: 'Nachhilfe Mathe 8. Klasse', category: 'Nachhilfe', description: 'Suche Mathe-Nachhilfe für meinen Sohn (14). 1-2x pro Woche.', location: 'Seesen', lat: 51.89, lng: 10.17, payment: '18 € / Stunde', date: '2025-02-01', createdBy: 'user3', createdAt: new Date().toISOString(), status: 'offen' },
            { id: 'job2', title: 'Hundesitting Samstag', category: 'Hundesitting', description: 'Golden Retriever braucht Betreuung am Samstag.', location: 'Goslar', lat: 51.91, lng: 10.42, payment: '25 € / Tag', date: '2025-02-08', createdBy: 'user2', createdAt: new Date().toISOString(), status: 'offen' }
        ];
        DB.save();
    }

    // ==================== STANDORT ====================
    function updateLocation(name, lat, lng, radius) {
        userLocation = { lat, lng, name };
        userCoordinates = { lat, lng };
        radiusFilter = radius;
        localStorage.setItem('mf_location', JSON.stringify(userLocation));
        localStorage.setItem('mf_radius', radius.toString());
    }

    function calculateDistance(lat1,lng1,lat2,lng2) {
        const R=6371, dLat=(lat2-lat1)*Math.PI/180, dLng=(lng2-lng1)*Math.PI/180;
        const a=Math.sin(dLat/2)**2+Math.cos(lat1*Math.PI/180)*Math.cos(lat2*Math.PI/180)*Math.sin(dLng/2)**2;
        return Math.round(R*2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a))*10)/10;
    }
    function getDistanceText(job) { if(!userCoordinates||!job.lat||!job.lng)return null; const d=calculateDistance(userCoordinates.lat,userCoordinates.lng,job.lat,job.lng); return d<1?'< 1 km':`${d} km`; }
    function sortJobsByDistance(jobs) { if(!userCoordinates)return jobs; return jobs.sort((a,b)=>calculateDistance(userCoordinates.lat,userCoordinates.lng,a.lat||52.5,a.lng||13.4)-calculateDistance(userCoordinates.lat,userCoordinates.lng,b.lat||52.5,b.lng||13.4)); }

    // ==================== NAVIGATION ====================
    function navigateTo(page, data=null, addToHistory=true) {
        if(addToHistory&&currentPage&&currentPage!==page){navigationHistory.push({page:currentPage,data:currentPageData});}
        currentPage=page; currentPageData=data;
        updateHeader(page); updateBottomNav(page);
        if(!currentUser&&page!=='login'){showLoginScreen();return;}
        switch(page){case'jobs':showJobsScreen();break;case'create':showCreateJobScreen();break;case'chats':showChatsScreen();break;case'profile':showProfileScreen();break;case'settings':showSettingsScreen();break;case'job-detail':showJobDetailScreen(data);break;case'user-profile':showUserProfileScreen(data);break;case'chat':showChatScreen(data);break;case'my-jobs':showMyJobs();break;case'my-applications':showMyApplications();break;case'edit-profile':editProfileScreen();break;case'feedback':showFeedbackScreen();break;case'delete-account':showDeleteAccountScreen();break;default:showJobsScreen();}
    }

    function goBack() { if(navigationHistory.length>0){const prev=navigationHistory.pop();navigateTo(prev.page,prev.data,false);}else navigateTo('jobs'); }
    
    function updateHeader(page) {
        const container=document.getElementById('app-header-container');
        const mainPages=['jobs','create','chats','profile','settings'];
        let showBack=!mainPages.includes(page)&&page!=='login', title='';
        switch(page){case'jobs':title='MiniJob Finder';break;case'create':title='Job erstellen';break;case'chats':title='Nachrichten';break;case'profile':title='Mein Profil';break;case'settings':title='Einstellungen';break;case'job-detail':title='Job-Details';break;case'user-profile':title='Nutzerprofil';break;case'chat':title='Chat';break;case'my-jobs':title='Meine Jobs';break;case'my-applications':title='Bewerbungen';break;case'edit-profile':title='Profil bearbeiten';break;case'feedback':title='Feedback';break;case'delete-account':title='Account löschen';break;default:title='';}
        if(showBack)container.innerHTML=`<div class="app-header"><button class="back-arrow" onclick="goBack()">←</button><span class="header-title">${title}</span></div>`;
        else if(page==='login')container.innerHTML='';
        else container.innerHTML=`<div class="app-header"><span style="font-size:22px">💼</span><h1 style="font-size:18px">MiniJob Finder</h1><button class="location-badge" onclick="showLocationModal()"><span class="material-icons" style="font-size:14px">location_on</span><span>${(userLocation?.name||'Ort').substring(0,12)}</span></button></div>`;
    }
    
    function updateBottomNav(page) {
        document.querySelectorAll('.nav-item').forEach(item=>item.classList.toggle('active',item.dataset.page===page||(page==='settings'&&item.dataset.page==='profile')));
    }

    function showToast(msg) {
        const e=document.querySelector('.toast'); if(e)e.remove();
        const t=document.createElement('div'); t.className='toast'; t.textContent=msg;
        document.body.appendChild(t); setTimeout(()=>t.remove(),3000);
    }

    function escapeHtml(t) { if(!t)return''; const d=document.createElement('div'); d.textContent=t; return d.innerHTML; }
    function generateId() { return'id_'+Date.now()+'_'+Math.random().toString(36).substr(2,9); }

    // ==================== LOCATION MODAL ====================
    function showLocationModal() {
        document.querySelector('.modal-overlay')?.remove();
        const overlay = document.createElement('div'); overlay.className = 'modal-overlay'; overlay.id = 'location-modal';
        overlay.innerHTML = `
            <div class="modal-content" onclick="event.stopPropagation()">
                <div style="display:flex;align-items:center;gap:8px;margin-bottom:16px">
                    <button class="back-arrow" onclick="closeLocationModal()">←</button>
                    <h2 style="font-size:18px">📍 Standort ändern</h2>
                </div>
                <div class="form-group"><label>Stadt / Ort</label><input type="text" id="modal-location-input" class="form-input" placeholder="z.B. Seesen, Berlin..." value="${escapeHtml(userLocation?.name||'')}"></div>
                <div class="form-group"><label>Suchradius</label><select id="modal-radius-input" class="form-input">${radiusOptions.map(r=>`<option value="${r}" ${r===radiusFilter?'selected':''}>${r} km</option>`).join('')}</select></div>
                <div style="display:flex;gap:8px"><button class="btn btn-outline" onclick="closeLocationModal()">Abbrechen</button><button class="btn btn-accent" onclick="saveLocationFromModal()">Speichern</button></div>
            </div>`;
        document.body.appendChild(overlay);
        overlay.addEventListener('click', (e) => { if (e.target === overlay) closeLocationModal(); });
        setTimeout(() => document.getElementById('modal-location-input')?.focus(), 200);
    }

    function closeLocationModal() { document.getElementById('location-modal')?.remove(); }

    function saveLocationFromModal() {
        const city = document.getElementById('modal-location-input')?.value?.trim();
        const radius = parseInt(document.getElementById('modal-radius-input')?.value || '50');
        if (!city) { showToast('Bitte Stadt eingeben'); return; }
        const cityCoords = { 'seesen':[51.89,10.17], 'goslar':[51.91,10.42], 'berlin':[52.52,13.40], 'hamburg':[53.55,9.99], 'münchen':[48.13,11.58], 'köln':[50.94,6.96] };
        let coords = [52.52, 13.40];
        for (const [c, coord] of Object.entries(cityCoords)) { if (city.toLowerCase().includes(c)) { coords = coord; break; } }
        updateLocation(city, coords[0], coords[1], radius);
        closeLocationModal();
        showToast(`📍 ${city} (${radius} km)`);
        if (currentPage === 'settings') showSettingsScreen(); else if (currentPage === 'jobs') showJobsScreen();
    }

    // ==================== LOGIN ====================
    function showLoginScreen() {
        currentPage='login'; document.getElementById('bottom-nav').classList.add('hidden'); document.getElementById('app-header-container').innerHTML='';
        document.getElementById('main-content').innerHTML=`
            <div style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:80vh;padding:20px">
                <span style="font-size:60px">💼</span>
                <h2 style="font-family:'Poppins',sans-serif;font-size:24px;color:var(--primary-blue);margin:8px 0">MiniJob Finder</h2>
                <p style="color:var(--text-secondary);margin-bottom:16px;text-align:center">Finde Minijobs in deiner Nähe</p>
                ${userLocation?`<p style="color:var(--success);margin-bottom:14px">📍 ${userLocation.name}</p>`:''}
                <div style="width:100%"><div class="form-group"><label>E-Mail</label><input type="email" id="login-email" class="form-input" placeholder="max@test.de"></div>
                <div class="form-group"><label>Passwort</label><input type="password" id="login-password" class="form-input" placeholder="123456" onkeypress="if(event.key==='Enter')login()"></div>
                <button class="btn btn-accent" onclick="login()">Anmelden</button>
                <button class="btn btn-outline" onclick="showRegisterScreen()" style="margin-top:8px">Neues Konto</button>
                <div style="background:var(--card);border-radius:var(--radius-sm);padding:12px;margin-top:14px;text-align:center;font-size:11px"><strong>Demo:</strong><br>📧 max@test.de | 🔑 123456<br>📧 herr-mueller@test.de | 🔑 123456</div></div></div>`;
    }

    function showRegisterScreen() {
        document.getElementById('main-content').innerHTML=`
            <div style="padding:16px"><button class="back-arrow" onclick="showLoginScreen()">←</button>
            <h2 style="margin:14px 0;text-align:center">Konto erstellen</h2>
            <div class="form-group"><label>Name</label><input type="text" id="reg-name" class="form-input" placeholder="Dein Name"></div>
            <div class="form-group"><label>E-Mail</label><input type="email" id="reg-email" class="form-input" placeholder="deine@email.de"></div>
            <div class="form-group"><label>Passwort</label><input type="password" id="reg-password" class="form-input" placeholder="Mind. 6 Zeichen"></div>
            <div class="form-group"><label>Geburtsdatum (mind. 13 Jahre)</label><input type="date" id="reg-birthdate" class="form-input"></div>
            <button class="btn btn-accent" onclick="register()">Registrieren</button></div>`;
    }

    function login() {
        const email=document.getElementById('login-email').value.trim().toLowerCase(), password=document.getElementById('login-password').value;
        const user=DB.users[email];
        if(user&&user.password===password){currentUser=user;localStorage.setItem('mf_currentUser',JSON.stringify({email}));document.getElementById('bottom-nav').classList.remove('hidden');navigationHistory=[];showToast(`👋 ${user.name}!`);navigateTo('jobs');}
        else showToast('❌ Falsche Anmeldedaten');
    }

    function register() {
        const name=document.getElementById('reg-name').value.trim(), email=document.getElementById('reg-email').value.trim().toLowerCase(), password=document.getElementById('reg-password').value, birthdate=document.getElementById('reg-birthdate').value;
        if(!name||!email||!password||!birthdate){showToast('Alle Felder ausfüllen');return;}
        if(DB.users[email]){showToast('E-Mail bereits registriert');return;}
        const age=Math.floor((new Date()-new Date(birthdate))/(365.25*24*60*60*1000));
        if(age<13){showToast('Mindestens 13 Jahre alt');return;}
        DB.users[email]={uid:generateId(),name,email,password,age,photoURL:'',bio:'',ratingSum:0,ratingCount:0,completedJobs:0,blockedUsers:[],createdAt:new Date().toISOString()};
        currentUser=DB.users[email]; localStorage.setItem('mf_currentUser',JSON.stringify({email}));
        document.getElementById('bottom-nav').classList.remove('hidden'); navigationHistory=[]; showToast('🎉 Willkommen!'); navigateTo('jobs');
    }

    function logout() { currentUser=null; localStorage.removeItem('mf_currentUser'); document.getElementById('bottom-nav').classList.add('hidden'); navigationHistory=[]; showLoginScreen(); showToast('👋 Abgemeldet'); }

    // ==================== BILD-UPLOAD ====================
    function triggerImageUpload() { document.getElementById('image-upload').click(); }
    function handleImageUpload(event) {
        const file=event.target.files[0]; if(!file)return;
        const reader=new FileReader();
        reader.onload=function(e){if(currentUser){currentUser.photoURL=e.target.result;if(DB.users[currentUser.email])DB.users[currentUser.email].photoURL=e.target.result;DB.save();showToast('📸 Profilbild gespeichert!');}};
        reader.readAsDataURL(file); event.target.value='';
    }

    // ==================== FEEDBACK ====================
    function showFeedbackScreen() {
        updateHeader('feedback');
        document.getElementById('main-content').innerHTML = `
            <div style="padding:16px"><h2 style="margin-bottom:8px">📝 Feedback</h2>
            <div class="form-group"><label>Betreff</label><input type="text" id="feedback-subject" class="form-input"></div>
            <div class="form-group"><label>Nachricht *</label><textarea id="feedback-message" class="form-textarea"></textarea></div>
            <button class="btn btn-feedback" onclick="sendFeedback()" style="background:#8E24AA;color:white">Senden</button></div>`;
    }

    function sendFeedback() {
        const message=document.getElementById('feedback-message').value.trim();
        if(!message){showToast('Nachricht schreiben');return;}
        window.location.href='mailto:'+FEEDBACK_EMAIL+'?subject=[MiniJob Finder] Feedback&body='+encodeURIComponent('Von: '+currentUser.name+' ('+currentUser.email+')\n\n'+message);
        showToast('✅ E-Mail-Client geöffnet');
    }

    // ==================== JOBS SCREEN ====================
    function showJobsScreen() {
        updateHeader('jobs');
        document.getElementById('main-content').innerHTML=`
            <input type="text" class="search-input" id="job-search" placeholder="🔍 Jobs suchen..." oninput="renderJobs()">
            <div class="filter-scroll">${categories.map(c=>`<button class="filter-chip ${(c==='Alle'&&!selectedCategory)||c===selectedCategory?'active':''}" onclick="setCategory('${c==='Alle'?'':c}')">${c}</button>`).join('')}</div>
            <div style="padding:4px 14px;font-size:11px"><span>Umkreis:</span> <select id="radius-select" class="form-input" style="width:auto;padding:4px 8px" onchange="changeRadius()">${radiusOptions.map(r=>`<option value="${r}" ${r===radiusFilter?'selected':''}>${r} km</option>`).join('')}</select> <span style="color:var(--text-secondary)">📍 ${userLocation?.name||'Unbekannt'}</span></div>
            <div id="jobs-list"></div>`;
        renderJobs();
    }

    function setCategory(cat) { selectedCategory=cat||null; showJobsScreen(); }
    function changeRadius() { radiusFilter=parseInt(document.getElementById('radius-select').value); localStorage.setItem('mf_radius',radiusFilter); renderJobs(); }

    function renderJobs() {
        const jobsList=document.getElementById('jobs-list'); if(!jobsList)return;
        
        // Daten neu laden (wichtig für Live-Updates!)
        DB.reload();
        
        let jobs=DB.jobs.filter(j=>j.status==='offen'||j.status==='reserviert');
        if(userCoordinates)jobs=jobs.filter(j=>{if(!j.lat||!j.lng)return true;return calculateDistance(userCoordinates.lat,userCoordinates.lng,j.lat,j.lng)<=radiusFilter;});
        if(selectedCategory)jobs=jobs.filter(j=>j.category===selectedCategory);
        const s=document.getElementById('job-search')?.value?.toLowerCase()||'';
        if(s)jobs=jobs.filter(j=>j.title.toLowerCase().includes(s)||j.description.toLowerCase().includes(s)||j.location.toLowerCase().includes(s));
        if(userCoordinates)jobs=sortJobsByDistance(jobs);

        if(jobs.length===0){
            jobsList.innerHTML=`<div class="empty-state"><span class="material-icons">rocket_launch</span><h2>Keine Jobs im Umkreis</h2><p>Erstelle den ersten Job!</p><button class="btn btn-accent" onclick="navigateTo('create')" style="margin-top:12px">Job erstellen</button></div>`;
            return;
        }

        jobsList.innerHTML=jobs.map(job=>{
            const creator=Object.values(DB.users).find(u=>u.uid===job.createdBy);
            const dist=getDistanceText(job);
            const isReserved=job.status==='reserviert';
            return`<div class="card job-card ${isReserved?'reserved':''}" onclick="navigateTo('job-detail','${job.id}')" style="position:relative">
                <div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:6px">
                    <strong style="font-size:14px;flex:1">${escapeHtml(job.title)}</strong>
                    <span class="job-category">${escapeHtml(job.category)}</span>
                </div>
                <p style="color:var(--text-secondary);font-size:12px;margin-bottom:6px">${escapeHtml(job.description.substring(0,80))}...</p>
                <div style="display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--text-secondary)">
                    <span>📍 ${escapeHtml(job.location)}</span>
                    ${dist?`<span class="distance-badge">📏 ${dist}</span>`:''}
                    <span style="color:var(--success);font-weight:700">💰 ${escapeHtml(job.payment)}</span>
                </div>
                ${isReserved?`<div style="margin-top:6px"><span class="status-badge reserviert">🔒 Reserviert</span></div>`:''}
            </div>`;
        }).join('');
    }

    // ==================== JOB DETAIL MIT RESERVIEREN ====================
    function showJobDetailScreen(jobId) {
        updateHeader('job-detail');
        DB.reload();
        const job=DB.jobs.find(j=>j.id===jobId);
        if(!job){document.getElementById('main-content').innerHTML='<div class="empty-state"><p>Job nicht gefunden</p></div>';return;}
        const creator=Object.values(DB.users).find(u=>u.uid===job.createdBy);
        const isOwner=job.createdBy===currentUser?.uid;
        const isReserved=job.status==='reserviert';
        const isOffen=job.status==='offen';

        document.getElementById('main-content').innerHTML=`
            <div style="padding:14px">
                <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;margin-bottom:12px">
                    <span class="job-category">${escapeHtml(job.category)}</span>
                    <span class="status-badge ${job.status}">${job.status==='offen'?'✅ Offen':job.status==='reserviert'?'🔒 Reserviert':job.status}</span>
                </div>
                <h2 style="font-size:18px;margin-bottom:8px">${escapeHtml(job.title)}</h2>
                <p style="font-size:13px;line-height:1.5;margin-bottom:14px;color:var(--text-secondary)">${escapeHtml(job.description)}</p>
                <div style="background:var(--card);padding:12px;border-radius:var(--radius-sm);margin-bottom:14px;font-size:12px">
                    <p>📍 ${escapeHtml(job.location)}</p><p>💰 ${escapeHtml(job.payment)}</p>
                    <p>📅 ${new Date(job.date).toLocaleDateString('de-DE')}</p>
                    <p>🕐 Erstellt: ${new Date(job.createdAt).toLocaleDateString('de-DE')}</p>
                </div>
                ${creator?`<div class="card" style="margin:0 0 14px 0" onclick="navigateTo('user-profile','${creator.uid}')"><div style="display:flex;align-items:center;gap:10px"><div style="width:40px;height:40px;border-radius:50%;background:var(--primary-blue);color:white;display:flex;align-items:center;justify-content:center;font-weight:700">${creator.name.charAt(0)}</div><div><strong>${escapeHtml(creator.name)}</strong><div style="font-size:11px;color:var(--text-secondary)">${creator.age}J</div></div></div></div>`:''}
                
                ${isOffen&&!isOwner?`<button class="btn btn-accent" onclick="applyForJob('${job.id}')">📩 Jetzt bewerben</button>`:''}
                ${isReserved&&!isOwner?`<button class="btn btn-outline" disabled style="opacity:0.6">🔒 Bereits reserviert</button>`:''}
                
                ${isOwner&&isOffen?`<button class="btn btn-reserve" onclick="reserveJob('${job.id}')">🔒 Für Bewerber reservieren</button>`:''}
                ${isOwner&&isReserved?`<button class="btn btn-unreserve" onclick="unreserveJob('${job.id}')">🔓 Reservierung aufheben</button>`:''}
                
                ${isOwner?`<button class="btn btn-danger" onclick="deleteJob('${job.id}')" style="margin-top:6px">🗑️ Job löschen</button>`:''}
            </div>`;
    }

    function applyForJob(jobId) {
        const msg=prompt('💬 Nachricht an den Anbieter:');
        if(!msg)return;
        DB.applications.push({id:generateId(),jobId,applicantId:currentUser.uid,applicantName:currentUser.name,message:msg,status:'ausstehend',createdAt:new Date().toISOString()});
        const job=DB.jobs.find(j=>j.id===jobId);
        if(job)startChatWithMessage(job.createdBy,`📩 Bewerbung für "${job.title}":\n\n${msg}\n\nVon: ${currentUser.name}`);
        DB.save();
        showToast('✅ Bewerbung gesendet! Der Anbieter kann den Job jetzt für dich reservieren.');
    }

    // ==================== JOB RESERVIEREN/FREIGEBEN ====================
    function reserveJob(jobId) {
        if(!confirm('🔒 Job reservieren?\n\nDer Job wird als "Reserviert" markiert und andere sehen, dass er vergeben sein könnte.\n\nDu kannst die Reservierung jederzeit aufheben.')) return;
        
        const jobIndex = DB._jobs.findIndex(j=>j.id===jobId);
        if(jobIndex>-1){
            DB._jobs[jobIndex].status = 'reserviert';
            DB.save();
            showToast('🔒 Job reserviert!');
            navigateTo('job-detail', jobId);
        }
    }

    function unreserveJob(jobId) {
        if(!confirm('🔓 Reservierung aufheben?\n\nDer Job ist dann wieder für alle sichtbar und offen.')) return;
        
        const jobIndex = DB._jobs.findIndex(j=>j.id===jobId);
        if(jobIndex>-1){
            DB._jobs[jobIndex].status = 'offen';
            DB.save();
            showToast('🔓 Job wieder offen!');
            navigateTo('job-detail', jobId);
        }
    }

    function deleteJob(jobId) { if(!confirm('Job löschen?'))return; DB.jobs=DB.jobs.filter(j=>j.id!==jobId); DB.save(); showToast('Job gelöscht'); goBack(); }

    // ==================== CREATE JOB ====================
    function showCreateJobScreen() {
        updateHeader('create');
        document.getElementById('main-content').innerHTML=`
            <div style="padding:14px"><h2>📝 Neuen Job erstellen</h2>
            <div class="form-group"><label>Titel *</label><input type="text" id="job-title" class="form-input" placeholder="z.B. Nachhilfe"></div>
            <div class="form-group"><label>Kategorie *</label><select id="job-category" class="form-input" onchange="document.getElementById('custom-cat').style.display=this.value==='andere'?'block':'none'"><option value="">Wählen...</option>${categories.filter(c=>c!=='Alle').map(c=>`<option value="${c}">${c}</option>`).join('')}<option value="andere">➕ Eigene...</option></select><input type="text" id="custom-cat" class="form-input" placeholder="Kategorie" style="display:none;margin-top:6px"></div>
            <div class="form-group"><label>Beschreibung *</label><textarea id="job-description" class="form-textarea"></textarea></div>
            <div class="form-group"><label>Ort *</label><input type="text" id="job-location" class="form-input" value="${escapeHtml(userLocation?.name||'')}"></div>
            <div class="form-group"><label>Bezahlung *</label><input type="text" id="job-payment" class="form-input" placeholder="z.B. 15 €/Std"></div>
            <button class="btn btn-accent" onclick="createJob()">Veröffentlichen</button></div>`;
    }

    function createJob() {
        const title=document.getElementById('job-title').value.trim(), description=document.getElementById('job-description').value.trim(), location=document.getElementById('job-location').value.trim(), payment=document.getElementById('job-payment').value.trim();
        let category=document.getElementById('job-category').value;
        if(category==='andere')category=document.getElementById('custom-cat').value.trim();
        if(!title||!category||!description||!location||!payment){showToast('Alle Felder ausfüllen');return;}
        DB.jobs.unshift({id:generateId(),title,category,description,location,payment,lat:userLocation?.lat||51.89,lng:userLocation?.lng||10.17,date:new Date().toISOString().split('T')[0],createdBy:currentUser.uid,createdAt:new Date().toISOString(),status:'offen'});
        DB.save();
        showToast('🎉 Job veröffentlicht!');
        navigateTo('jobs');
    }

    // ==================== PROFILE & SETTINGS ====================
    function showProfileScreen() {
        updateHeader('profile');
        const myJobs=DB.jobs.filter(j=>j.createdBy===currentUser.uid).length;
        const myApps=DB.applications.filter(a=>a.applicantId===currentUser.uid).length;
        document.getElementById('main-content').innerHTML=`
            <div style="background:var(--card);padding:20px;text-align:center;border-radius:0 0 var(--radius) var(--radius);margin-bottom:14px">
                <div class="profile-avatar" onclick="triggerImageUpload()">${currentUser.photoURL?`<img src="${currentUser.photoURL}">`:currentUser.name.charAt(0)}</div>
                <h2>${escapeHtml(currentUser.name)}</h2><p>${currentUser.age} Jahre</p>
                <div style="display:flex;justify-content:center;gap:18px;margin-top:8px"><div><strong>${myJobs}</strong><br><span style="font-size:11px">Jobs</span></div><div><strong>${myApps}</strong><br><span style="font-size:11px">Bewerb.</span></div></div>
            </div>
            <div style="padding:14px;display:flex;flex-direction:column;gap:6px">
                <button class="btn btn-outline" onclick="navigateTo('my-jobs')">Meine Jobs</button>
                <button class="btn btn-outline" onclick="navigateTo('settings')">Einstellungen</button>
                <button class="btn" onclick="navigateTo('feedback')" style="background:#8E24AA;color:white">Feedback</button>
            </div>`;
    }

    function showSettingsScreen() {
        updateHeader('settings');
        const isDark=document.body.getAttribute('data-theme')==='dark';
        document.getElementById('main-content').innerHTML=`
            <div style="padding:14px">
                <div style="background:var(--card);border-radius:var(--radius);padding:16px;margin-bottom:14px">
                    <div style="display:flex;align-items:center;gap:10px">
                        <div style="width:45px;height:45px;border-radius:50%;background:var(--primary-blue);color:white;display:flex;align-items:center;justify-content:center;font-weight:700">${currentUser.name.charAt(0)}</div>
                        <div><strong>${escapeHtml(currentUser.name)}</strong><p style="font-size:12px;color:var(--text-secondary)">${escapeHtml(currentUser.email)}</p></div>
                    </div>
                </div>
                <div style="background:var(--card);border-radius:var(--radius);padding:4px 14px;margin-bottom:14px">
                    <div class="settings-item" onclick="toggleTheme();showSettingsScreen()"><div class="settings-item-left"><span class="material-icons">${isDark?'dark_mode':'light_mode'}</span>Dark Mode</div><div class="toggle-switch ${isDark?'active':''}"></div></div>
                    <div class="settings-item" onclick="showLocationModal()"><div class="settings-item-left"><span class="material-icons">edit_location</span>Standort: ${userLocation?.name||'?'} (${radiusFilter}km)</div></div>
                    <div class="settings-item" onclick="navigateTo('edit-profile')"><div class="settings-item-left"><span class="material-icons">edit</span>Profil bearbeiten</div></div>
                </div>
                <button class="btn btn-danger" onclick="logout()">Abmelden</button>
                <button class="btn" onclick="navigateTo('delete-account')" style="background:#B71C1C;color:white;margin-top:8px">Account löschen</button>
            </div>`;
    }

    function toggleTheme() {
        const t=document.body.getAttribute('data-theme')==='light'?'dark':'light';
        document.body.setAttribute('data-theme',t); localStorage.setItem('mf_theme',t);
    }

    function showMyJobs() {
        updateHeader('my-jobs');
        const myJobs=DB.jobs.filter(j=>j.createdBy===currentUser.uid);
        const c=document.getElementById('main-content');
        if(myJobs.length===0){c.innerHTML=`<div class="empty-state"><h3>Keine Jobs</h3></div>`;return;}
        c.innerHTML=`<div style="padding:14px">${myJobs.map(j=>`<div class="card" onclick="navigateTo('job-detail','${j.id}')"><div style="display:flex;justify-content:space-between"><strong>${escapeHtml(j.title)}</strong><span class="status-badge ${j.status}">${j.status}</span></div><p style="font-size:11px">${escapeHtml(j.location)} • ${escapeHtml(j.payment)}</p></div>`).join('')}</div>`;
    }

    function showMyApplications() {
        updateHeader('my-applications');
        const myApps=DB.applications.filter(a=>a.applicantId===currentUser.uid);
        const c=document.getElementById('main-content');
        if(myApps.length===0){c.innerHTML=`<div class="empty-state"><h3>Keine Bewerbungen</h3></div>`;return;}
        c.innerHTML=`<div style="padding:14px">${myApps.map(a=>{const j=DB.jobs.find(j=>j.id===a.jobId);return`<div class="card"><strong>${escapeHtml(j?.title||'Job weg')}</strong><p style="font-size:11px">Status: ${a.status}</p></div>`;}).join('')}</div>`;
    }

    function editProfileScreen() {
        updateHeader('edit-profile');
        document.getElementById('main-content').innerHTML=`
            <div style="padding:14px"><div style="text-align:center;margin-bottom:16px"><div class="profile-avatar" onclick="triggerImageUpload()">${currentUser.photoURL?`<img src="${currentUser.photoURL}">`:currentUser.name.charAt(0)}</div></div>
            <div class="form-group"><label>Name</label><input type="text" id="edit-name" class="form-input" value="${escapeHtml(currentUser.name)}"></div>
            <div class="form-group"><label>Bio</label><textarea id="edit-bio" class="form-textarea">${escapeHtml(currentUser.bio||'')}</textarea></div>
            <button class="btn btn-accent" onclick="saveProfile()">Speichern</button></div>`;
    }

    function saveProfile() {
        const name=document.getElementById('edit-name').value.trim(), bio=document.getElementById('edit-bio').value.trim();
        if(!name){showToast('Name erforderlich');return;}
        currentUser.name=name; currentUser.bio=bio;
        if(DB.users[currentUser.email]){DB.users[currentUser.email].name=name;DB.users[currentUser.email].bio=bio;}
        DB.save(); showToast('✅ Gespeichert!'); goBack();
    }

    function showUserProfileScreen(userId) {
        updateHeader('user-profile');
        const user=Object.values(DB.users).find(u=>u.uid===userId);
        if(!user)return;
        document.getElementById('main-content').innerHTML=`
            <div style="background:var(--card);padding:16px;text-align:center;margin-bottom:12px">
                <div style="width:60px;height:60px;border-radius:50%;background:var(--primary-blue);color:white;display:flex;align-items:center;justify-content:center;font-weight:700;margin:0 auto">${user.name.charAt(0)}</div>
                <h2>${escapeHtml(user.name)}</h2><p>${user.age}J</p>
            </div>
            <div style="padding:14px">${user.uid!==currentUser?.uid?`<button class="btn btn-primary" onclick="startChat('${user.uid}')">💬 Nachricht</button>`:''}</div>`;
    }

    // ==================== CHATS ====================
    function showChatsScreen() {
        updateHeader('chats');
        const myChats=DB.chats.filter(c=>c.participants.includes(currentUser.uid));
        const sorted=[...myChats].sort((a,b)=>{
            const aM=DB.messages[a.id]||[], bM=DB.messages[b.id]||[];
            return(bM.length>0?new Date(bM[bM.length-1].timestamp).getTime():0)-(aM.length>0?new Date(aM[aM.length-1].timestamp).getTime():0);
        });
        const c=document.getElementById('main-content');
        if(sorted.length===0){c.innerHTML=`<div class="empty-state"><span class="material-icons">chat_bubble_outline</span><h3>Keine Chats</h3></div>`;return;}
        c.innerHTML=`<div style="padding:14px">${sorted.map(chat=>{
            const oId=chat.participants.find(id=>id!==currentUser.uid), oU=Object.values(DB.users).find(u=>u.uid===oId);
            const msgs=DB.messages[chat.id]||[], last=msgs[msgs.length-1];
            return`<div class="card" onclick="navigateTo('chat','${chat.id}')"><div style="display:flex;align-items:center;gap:10px"><div style="width:38px;height:38px;border-radius:50%;background:var(--primary-blue);color:white;display:flex;align-items:center;justify-content:center;font-weight:700">${(oU?.name||'?')[0]}</div><div style="flex:1"><strong>${escapeHtml(oU?.name||'?')}</strong><p style="font-size:11px;color:var(--text-secondary)">${last?escapeHtml(last.text.substring(0,30)):'Keine Nachrichten'}</p></div></div></div>`;
        }).join('')}</div>`;
    }

    function startChat(otherUserId) { startChatWithMessage(otherUserId,null); }
    function startChatWithMessage(uid,msg) {
        let chat=DB.chats.find(c=>c.participants.includes(currentUser.uid)&&c.participants.includes(uid));
        if(!chat){chat={id:generateId(),participants:[currentUser.uid,uid],createdAt:new Date().toISOString(),lastRead:{}};DB.chats.push(chat);DB.messages[chat.id]=[];}
        if(msg)DB.messages[chat.id].push({id:generateId(),senderId:currentUser.uid,text:msg,timestamp:new Date().toISOString()});
        DB.save(); navigateTo('chat',chat.id);
    }

    function showChatScreen(chatId) {
        updateHeader('chat');
        const chat=DB.chats.find(c=>c.id===chatId);
        if(!chat)return;
        if(!chat.lastRead)chat.lastRead={}; chat.lastRead[currentUser.uid]=Date.now(); DB.save();
        const msgs=DB.messages[chatId]||[];
        document.getElementById('main-content').innerHTML=`<div style="display:flex;flex-direction:column;height:calc(100vh-155px)"><div id="msg-container" style="flex:1;overflow-y:auto;padding:10px">${msgs.length===0?'<p style="text-align:center;margin-top:40px;color:var(--text-secondary)">💬 Keine Nachrichten</p>':''}</div><div style="padding:8px;display:flex;gap:6px;border-top:1px solid var(--border)"><input type="text" id="msg-input" class="form-input" placeholder="Nachricht..." style="flex:1" onkeypress="if(event.key==='Enter')sendMessage('${chatId}')"><button class="btn btn-primary" onclick="sendMessage('${chatId}')" style="width:auto">➤</button></div></div>`;
        renderMessages(chatId);
    }

    function renderMessages(chatId) {
        const c=document.getElementById('msg-container'); if(!c)return;
        const msgs=DB.messages[chatId]||[];
        c.innerHTML=msgs.map(m=>`<div style="display:flex;justify-content:${m.senderId===currentUser.uid?'flex-end':'flex-start'}"><div class="chat-bubble ${m.senderId===currentUser.uid?'sent':'received'}">${escapeHtml(m.text)}<div style="font-size:9px;opacity:0.6;margin-top:3px">${new Date(m.timestamp).toLocaleTimeString('de-DE',{hour:'2-digit',minute:'2-digit'})}</div></div></div>`).join('');
        if(msgs.length>0)c.scrollTop=c.scrollHeight;
    }

    function sendMessage(chatId) {
        const i=document.getElementById('msg-input'), t=i.value.trim(); if(!t)return;
        if(!DB.messages[chatId])DB.messages[chatId]=[];
        DB.messages[chatId].push({id:generateId(),senderId:currentUser.uid,text:t,timestamp:new Date().toISOString()});
        DB.save(); i.value=''; renderMessages(chatId);
    }

    // ==================== ACCOUNT LÖSCHEN ====================
    function showDeleteAccountScreen() {
        updateHeader('delete-account');
        document.getElementById('main-content').innerHTML = `
            <div style="padding:16px">
                <div style="text-align:center;margin-bottom:20px"><span class="material-icons" style="font-size:64px;color:var(--danger)">warning_amber</span>
                <h2 style="color:var(--danger)">Account löschen</h2></div>
                <div class="form-group"><label>Passwort zur Bestätigung</label><input type="password" id="delete-password" class="form-input"></div>
                <label style="display:flex;align-items:center;gap:8px;margin-bottom:14px"><input type="checkbox" id="delete-confirm">Ja, ich möchte meinen Account unwiderruflich löschen</label>
                <button class="btn btn-delete-account" onclick="deleteAccount()" style="background:#B71C1C;color:white">🗑️ Account löschen</button>
                <button class="btn btn-outline" onclick="goBack()" style="margin-top:8px">Abbrechen</button>
            </div>`;
    }

    function deleteAccount() {
        if(!document.getElementById('delete-confirm').checked){showToast('Bitte bestätigen');return;}
        if(document.getElementById('delete-password').value!==currentUser.password){showToast('Falsches Passwort');return;}
        if(!confirm('WIRKLICH löschen?'))return;
        const uid=currentUser.uid, email=currentUser.email;
        DB.jobs=DB.jobs.filter(j=>j.createdBy!==uid);
        DB.applications=DB.applications.filter(a=>a.applicantId!==uid);
        DB.chats.forEach(c=>{if(c.participants.includes(uid))delete DB.messages[c.id];});
        DB.chats=DB.chats.filter(c=>!c.participants.includes(uid));
        delete DB.users[email]; DB.save();
        currentUser=null; localStorage.removeItem('mf_currentUser');
        document.getElementById('bottom-nav').classList.add('hidden');
        showToast('Account gelöscht'); showLoginScreen();
    }

    // ==================== START ====================
    const savedTheme=localStorage.getItem('mf_theme');
    if(savedTheme)document.body.setAttribute('data-theme',savedTheme);
    console.log('🚀 MiniJob Finder v4.0');
    console.log('🔄 Live-Updates zwischen Tabs aktiv');
    console.log('🔒 Job-Reservierung verfügbar');
    init();
</script>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions