import { readMembers, normalizeDate } from '../utils/members.js' import { readUsers, migrateUserRoles, getUserFromToken, verifyToken } from '../utils/auth.js' // Helper: returns array of upcoming birthdays within daysAhead (inclusive) function getUpcomingBirthdays(entries, daysAhead = 28) { const now = new Date() const results = [] // iterate entries with geburtsdatum and name for (const e of entries) { const raw = e.geburtsdatum if (!raw) continue const parsed = new Date(raw) if (isNaN(parsed.getTime())) continue // Build next occurrence for this year const thisYear = now.getFullYear() const occ = new Date(thisYear, parsed.getMonth(), parsed.getDate()) // If already passed this year, consider next year if (occ < now) { occ.setFullYear(thisYear + 1) } const diffDays = Math.ceil((occ - now) / (1000 * 60 * 60 * 24)) if (diffDays >= 0 && diffDays <= daysAhead) { results.push({ name: e.name || `${e.firstName || ''} ${e.lastName || ''}`.trim(), dayMonth: `${String(occ.getDate()).padStart(2, '0')}.${String(occ.getMonth()+1).padStart(2, '0')}`, date: occ, diffDays }) } } // Sort by upcoming date results.sort((a, b) => a.date - b.date) return results } export default defineEventHandler(async (event) => { try { // Determine viewer for visibility rules; token optional const token = getCookie(event, 'auth_token') let currentUser = null if (token) { const decoded = verifyToken(token) if (decoded) { currentUser = await getUserFromToken(token) } } const manualMembers = await readMembers() const registeredUsers = await readUsers() // Build unified list of candidates with geburtsdatum and visibility const candidates = [] for (const m of manualMembers) { const isAccepted = m.active === true || (m.status && String(m.status).toLowerCase() === 'accepted') || m.accepted === true if (!isAccepted) continue const vis = m.visibility || {} const showBirthday = vis.showBirthday === undefined ? true : Boolean(vis.showBirthday) candidates.push({ name: `${m.firstName || ''} ${m.lastName || ''}`.trim(), geburtsdatum: m.geburtsdatum, visibility: { showBirthday }, source: 'manual' }) } for (const u of registeredUsers) { if (!u.active) continue const vis = u.visibility || {} const showBirthday = vis.showBirthday === undefined ? true : Boolean(vis.showBirthday) candidates.push({ name: u.name, geburtsdatum: u.geburtsdatum, visibility: { showBirthday }, source: 'login' }) } // Respect visibility: if viewer is vorstand they see all birthdays const isPrivilegedViewer = currentUser ? (Array.isArray(currentUser.roles) ? currentUser.roles.includes('vorstand') : currentUser.role === 'vorstand') : false const filtered = candidates.filter(c => c.geburtsdatum && (isPrivilegedViewer || c.visibility.showBirthday === true)) const upcoming = getUpcomingBirthdays(filtered, 28) // Return only next 4 weeks entries with name and dayMonth return { success: true, birthdays: upcoming.map(b => ({ name: b.name, dayMonth: b.dayMonth, inDays: b.diffDays })) } } catch (error) { console.error('Fehler beim Abrufen der Geburtstage:', error) throw error } })