Add DOCX export endpoint and Export button

- GET /api/export generates a Word document with all non-archived prayers
- Accepts ?status=active|answered|all and ?tag= query params to match
  the current filter/tag selection in the UI
- Document sections: Active Prayers + Answered Prayers with page break,
  each prayer showing person, request, answer, dates, and tags
- Styled with Palatino Linotype, page numbers in footer
- Export button in the toolbar triggers download of dated .docx file

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DReRqHxSYuVfCzTzQGD9hZ
This commit is contained in:
Claude committed 2026-07-18 23:36:25 +00:00
1 parent af836d4ec9
commit 2b3d6a540c
5 files changed
+383 -3

No files matched your search

+16
View File
@@ -214,6 +214,22 @@ body {
gap: .5rem;
}
.btn-export {
background: var(--surface);
border-color: var(--border);
color: var(--text-muted);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
font-size: .82rem;
padding: .38rem .8rem;
white-space: nowrap;
flex-shrink: 0;
}
.btn-export:hover {
color: var(--text);
border-color: var(--primary);
}
/* Search */
.search-wrap {
position: relative;
+11
View File
@@ -103,6 +103,13 @@ export default function App() {
setActiveTag(prev => prev === tag ? null : tag);
}
function handleExport() {
const params = new URLSearchParams();
params.set('status', filter);
if (activeTag) params.set('tag', activeTag);
window.location.href = `/api/export?${params.toString()}`;
}
const emptyMessage = search
? `No results for "${search}".`
: activeTag
@@ -167,6 +174,10 @@ export default function App() {
</button>
</div>
<button className="btn btn-export" onClick={handleExport} title="Export to Word">
↓ Export
</button>
<div className="search-wrap">
<span className="search-icon">⌕</span>
<input