mirror of
https://github.com/mmahdium/portfolio.git
synced 2026-08-15 20:52:49 +03:30
Epic 2: Resume Preview Page - All 5 stories completed Story 2-1: Create Resume Page Route - Add /resume standalone page with layout: false - Implement print mode detection (?print=true) - Add SEO meta tags (noindex for privacy) - Set page title "Resume - Ali Arghyani" Story 2-2: Create ResumePreview Container - Add single-column A4 container (210mm × 297mm) - Implement white background with 24px margins - Add print styles with .no-print class - Configure responsive layout Story 2-3: Create Header, Summary, Experience Components - Add ResumeHeader with profile photo, name, contact info - Add ResumeSummary with blue uppercase section header - Add ResumeExperience with sorted jobs and date formatting - Add image property to ResumeBasics interface - Integrate all components into ResumePreview Story 2-4: Create Education & Additional Info Components - Add ResumeEducation with date formatting - Add ResumeAdditionalInfo with skills, languages, certifications - Integrate components into ResumePreview Story 2-5: Create Download Button Component - Add ResumeDownloadButton FAB (fixed bottom-right) - Add download icon and "Download PDF" text - Implement print mode detection - Add placeholder click handler for Epic 3 integration - Responsive: text on desktop, icon-only on mobile Additional: - Add profile image to resume data (/img/AliProfile.webp) - Update sprint-status.yaml: all Epic 2 stories marked done Files Created: - app/pages/resume.vue - app/components/resume/ResumePreview.vue - app/components/resume/ResumeHeader.vue - app/components/resume/ResumeSummary.vue - app/components/resume/ResumeExperience.vue - app/components/resume/ResumeEducation.vue - app/components/resume/ResumeAdditionalInfo.vue - app/components/resume/ResumeDownloadButton.vue Files Modified: - app/types/resume.ts (added image property) - app/data/resume.en.ts (added profile image) - docs/sprint-artifacts/sprint-status.yaml (updated story statuses) - docs/sprint-artifacts/2-1-create-resume-page-route.md (completed) - docs/sprint-artifacts/2-2-create-resume-preview-container-component.md (completed) - docs/sprint-artifacts/2-3-create-resume-header-main-content-components.md (completed) - docs/sprint-artifacts/2-4-create-resume-sidebar-components.md (completed) - docs/sprint-artifacts/2-5-create-download-button-component.md (completed) Closes Epic 2 Closes Story 2-1, 2-2, 2-3, 2-4, 2-5
51 lines
1.5 KiB
Vue
51 lines
1.5 KiB
Vue
<script setup lang="ts">
|
|
import type { WorkExperience } from '~/types/resume'
|
|
|
|
interface Props {
|
|
work: WorkExperience[]
|
|
}
|
|
|
|
const props = defineProps<Props>()
|
|
const { formatDate } = useResumeData()
|
|
|
|
const sortedWork = computed(() => {
|
|
return [...props.work].sort((a, b) => {
|
|
const dateA = a.startDate || ''
|
|
const dateB = b.startDate || ''
|
|
return dateB.localeCompare(dateA)
|
|
})
|
|
})
|
|
|
|
function formatDateRange(start: string, end?: string): string {
|
|
const startFormatted = formatDate(start)
|
|
const endFormatted = end ? formatDate(end) : 'Present'
|
|
return `${startFormatted} - ${endFormatted}`
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<section class="mb-6">
|
|
<h2 class="text-base font-bold text-blue-600 uppercase border-b-2 border-blue-600 pb-1 mb-3">
|
|
Work Experience
|
|
</h2>
|
|
|
|
<div v-for="job in sortedWork" :key="job.company + job.startDate" class="mb-4 last:mb-0">
|
|
<div class="flex justify-between items-start">
|
|
<div>
|
|
<h3 class="text-sm font-semibold text-gray-800">{{ job.position }}</h3>
|
|
<p class="text-sm text-gray-600">{{ job.company }}</p>
|
|
</div>
|
|
<span class="text-sm text-gray-500 whitespace-nowrap">
|
|
{{ formatDateRange(job.startDate, job.endDate) }}
|
|
</span>
|
|
</div>
|
|
<ul class="mt-2 space-y-1">
|
|
<li v-for="(highlight, idx) in job.highlights" :key="idx"
|
|
class="text-sm text-gray-700 pl-4 relative before:content-['•'] before:absolute before:left-0">
|
|
{{ highlight }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
</template>
|