feat(export): download project photos as a grouped zip
Add POST /api/export {projectIds}: one folder per project (named after it),
photos named <lastname-firstname>.<ext>, with a generated initials SVG for
Members without a Slack photo. Dedupe image fetches, bounded concurrency, fflate
zip. Factor data.ts so routes + export share one fixtures/live gating path.
Frontend: Export-photos button downloads the zip.
This commit is contained in:
23
backend/src/data.ts
Normal file
23
backend/src/data.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { hasNaptaCredentials } from "./config.ts"
|
||||
import { fixtureMembers, fixtureProjects } from "./fixtures.ts"
|
||||
import { fetchNaptaProjectMembers, fetchNaptaProjects } from "./napta.ts"
|
||||
import { type EnrichResult, enrichWithSlackAvatars } from "./slack.ts"
|
||||
import type { DataSource, Project } from "./types.ts"
|
||||
|
||||
// Single source of truth for "fixtures vs live", shared by the API routes and
|
||||
// the Export so the gating logic isn't duplicated.
|
||||
|
||||
export async function getProjects(): Promise<{ source: DataSource; projects: Project[] }> {
|
||||
if (!hasNaptaCredentials) return { source: "fixture", projects: fixtureProjects }
|
||||
return { source: "napta", projects: await fetchNaptaProjects() }
|
||||
}
|
||||
|
||||
export async function getProjectMembers(
|
||||
projectId: string,
|
||||
): Promise<{ source: DataSource } & EnrichResult> {
|
||||
if (!hasNaptaCredentials) {
|
||||
return { source: "fixture", members: fixtureMembers(projectId), slack: "unconfigured" }
|
||||
}
|
||||
const enriched = await enrichWithSlackAvatars(await fetchNaptaProjectMembers(projectId))
|
||||
return { source: "napta", ...enriched }
|
||||
}
|
||||
Reference in New Issue
Block a user