91 lines
3.3 KiB
JavaScript
91 lines
3.3 KiB
JavaScript
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
|
|
}
|
|
})
|