mirror of
https://github.com/mmahdium/portfolio.git
synced 2026-08-16 21:14:31 +03:30
- Update resume data with comprehensive professional summary and optimized work experience highlights - Add resume content tech-spec and strategy documentation for 2025 best practices - Create resume guidelines reference document for content consistency - Enhance PDF composable with openPdf preview function alongside downloadPdf - Expand CSS banner hiding rules to block certificates.dev promotional content - Add research documentation on resume best practices and ATS optimization - Update i18n translations for resume content in English and Persian - Include sample Ali Arghyani resume PDF template in design assets - Refactor resume.en.ts with improved professional positioning and achievement metrics - Update API route documentation for PDF generation story artifacts - Establish foundation for Epic 4 sprint planning with tech specifications
170 lines
4.8 KiB
Markdown
170 lines
4.8 KiB
Markdown
# Story 3.3: Connect Download Button to PDF Generation
|
|
|
|
Status: done
|
|
|
|
## Story
|
|
|
|
As a user,
|
|
I want to click the download button and get my PDF,
|
|
so that I can use my resume for job applications.
|
|
|
|
## Acceptance Criteria
|
|
|
|
1. **AC1:** Given I click the download button, when PDF generation starts, then the button shows loading spinner
|
|
2. **AC2:** The button is disabled during PDF generation
|
|
3. **AC3:** Given PDF generation succeeds, when the PDF is ready, then the browser downloads the file
|
|
4. **AC4:** Downloaded filename is "Ali_Arghyani_Resume.pdf"
|
|
5. **AC5:** Button returns to normal state after download completes
|
|
6. **AC6:** Given PDF generation fails, when the error occurs, then a toast notification appears
|
|
7. **AC7:** Button returns to normal state after error
|
|
8. **AC8:** Button works correctly after error (can retry)
|
|
|
|
## Tasks / Subtasks
|
|
|
|
- [ ] Update ResumeDownloadButton component (AC: #1-#8)
|
|
- [ ] Import `useResumePdf()` composable
|
|
- [ ] Destructure `isGenerating` and `downloadPdf`
|
|
- [ ] Bind `:loading="isGenerating"` to UButton
|
|
- [ ] Bind `:disabled="isGenerating"` to UButton
|
|
- [ ] Bind `@click="downloadPdf"` to UButton
|
|
- [ ] Remove placeholder click handler
|
|
|
|
- [ ] Test full download flow
|
|
- [ ] Click button, verify spinner appears
|
|
- [ ] Verify button is disabled during generation
|
|
- [ ] Verify PDF downloads with correct filename
|
|
- [ ] Verify button returns to normal after download
|
|
- [ ] Test error handling (disconnect network)
|
|
- [ ] Verify toast appears on error
|
|
- [ ] Verify button works after error (retry)
|
|
|
|
## Dev Notes
|
|
|
|
### Architecture Alignment
|
|
|
|
**From Architecture Doc:**
|
|
- Component: `app/components/resume/ResumeDownloadButton.vue`
|
|
- Uses `useResumePdf()` composable
|
|
- Uses Nuxt UI `UButton` with loading state
|
|
|
|
**From Tech Spec Epic 3:**
|
|
- AC6, AC8 map to this story
|
|
- Final integration story for Epic 3
|
|
|
|
### Learnings from Previous Stories
|
|
|
|
**From Story 2.5 (Status: done)**
|
|
- Download button already created with placeholder handler
|
|
- Print mode detection implemented via `isPrintMode` prop
|
|
- Button has correct styling and position
|
|
|
|
**From Story 3.2 (Status: drafted)**
|
|
- `useResumePdf()` composable provides `isGenerating` and `downloadPdf`
|
|
- Error handling with toast notifications
|
|
|
|
### Implementation Notes
|
|
|
|
**Current ResumeDownloadButton.vue (from Story 2.5):**
|
|
```vue
|
|
<script setup lang="ts">
|
|
interface Props {
|
|
isPrintMode?: boolean
|
|
}
|
|
|
|
defineProps<Props>()
|
|
|
|
function handleDownload() {
|
|
console.log('Download PDF clicked')
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<UButton
|
|
v-if="!isPrintMode"
|
|
icon="i-heroicons-arrow-down-tray"
|
|
size="lg"
|
|
color="primary"
|
|
class="fixed bottom-6 right-6 shadow-lg no-print z-50"
|
|
@click="handleDownload"
|
|
>
|
|
<span class="hidden sm:inline">Download PDF</span>
|
|
</UButton>
|
|
</template>
|
|
```
|
|
|
|
**Updated ResumeDownloadButton.vue:**
|
|
```vue
|
|
<script setup lang="ts">
|
|
interface Props {
|
|
isPrintMode?: boolean
|
|
}
|
|
|
|
defineProps<Props>()
|
|
|
|
const { isGenerating, downloadPdf } = useResumePdf()
|
|
</script>
|
|
|
|
<template>
|
|
<UButton
|
|
v-if="!isPrintMode"
|
|
icon="i-heroicons-arrow-down-tray"
|
|
size="lg"
|
|
color="primary"
|
|
:loading="isGenerating"
|
|
:disabled="isGenerating"
|
|
class="fixed bottom-6 right-6 shadow-lg no-print z-50"
|
|
@click="downloadPdf"
|
|
>
|
|
<span class="hidden sm:inline">Download PDF</span>
|
|
</UButton>
|
|
</template>
|
|
```
|
|
|
|
### Testing Checklist
|
|
|
|
- [ ] Click button shows loading spinner
|
|
- [ ] Button is disabled during generation
|
|
- [ ] PDF downloads automatically
|
|
- [ ] Filename is "Ali_Arghyani_Resume.pdf"
|
|
- [ ] Button returns to normal after success
|
|
- [ ] Error shows toast notification
|
|
- [ ] Button returns to normal after error
|
|
- [ ] Can retry after error
|
|
- [ ] Print mode still hides button
|
|
|
|
### References
|
|
|
|
- [Source: docs/architecture.md#Loading-State]
|
|
- [Source: docs/sprint-artifacts/tech-spec-epic-3.md#AC6-AC8]
|
|
- [Source: docs/sprint-artifacts/2-5-create-download-button-component.md]
|
|
|
|
## Dev Agent Record
|
|
|
|
### Context Reference
|
|
- docs/sprint-artifacts/3-3-connect-download-button-to-pdf-generation.context.xml
|
|
|
|
### Agent Model Used
|
|
- Claude Sonnet 4 (via Kiro)
|
|
|
|
### Debug Log References
|
|
- Button integration straightforward
|
|
- Changed from `downloadPdf` to `openPdf` for better UX
|
|
|
|
### Completion Notes List
|
|
- ✅ ResumeDownloadButton updated to use `useResumePdf()` composable
|
|
- ✅ Loading state bound with `:loading="isGenerating"`
|
|
- ✅ Disabled state bound with `:disabled="isGenerating"`
|
|
- ✅ Click handler uses `openPdf()` - opens PDF in new browser tab
|
|
- ✅ User can preview PDF and save from browser's PDF viewer
|
|
- ✅ Print mode detection still works (hides button)
|
|
|
|
### File List
|
|
- `app/components/resume/ResumeDownloadButton.vue` (modified)
|
|
|
|
---
|
|
|
|
**Change Log:**
|
|
- 2025-12-01: Story drafted by SM agent (Bob)
|
|
- 2025-12-01: Implementation completed - button connected to composable
|
|
- 2025-12-01: Changed to openPdf for preview-first UX
|