|
2 | 2 | import type { CollectionEntry } from 'astro:content' |
3 | 3 | import type { AstroComponentFactory } from 'astro/runtime/server/index.js' |
4 | 4 | import HeadContent from '@components/Head/index.astro' |
5 | | -import Icon from '@components/Icon/index.astro' |
6 | | -import List from '@components/List/index.astro' |
7 | | -import ListItem from '@components/List/ListItem.astro' |
8 | | -import { formatPhoneNumber } from '@components/Footer/server' |
9 | | -import { formatMonthYear, formatDateContent, splitLocation } from '@components/Pages/Resume/server' |
| 5 | +import Contact from '@components/Pages/Resume/partials/Contact.astro' |
| 6 | +import Controls from '@components/Pages/Resume/partials/Controls.astro' |
| 7 | +import ExperienceCard from '@components/Pages/Resume/partials/ExperienceCard.astro' |
| 8 | +import Persona from '@components/Pages/Resume/partials/Persona.astro' |
| 9 | +import Skills from '@components/Pages/Resume/partials/Skills.astro' |
| 10 | +import Summary from '@components/Pages/Resume/partials/Summary.astro' |
10 | 11 |
|
11 | 12 | import '@styles/index.css' |
12 | 13 | import '@styles/icons.css' |
@@ -46,213 +47,77 @@ const socialEntries: SocialEntry[] = [...companyContact.social] |
46 | 47 | label: entry.displayName, |
47 | 48 | url: entry.url, |
48 | 49 | })) |
49 | | -const resumeLocation = `${companyContact.city}, ${companyContact.state}` |
50 | | -const resumePhoneNumber = formatPhoneNumber(companyContact.telephoneTollFree) |
51 | 50 | --- |
52 | 51 |
|
53 | 52 | <!doctype html> |
54 | | -<html lang="en" data-theme="light" class="min-h-full overflow-y-auto"> |
| 53 | +<html lang="en" data-theme="light" class="h-auto min-h-full overflow-y-auto"> |
55 | 54 | <head> |
56 | 55 | <HeadContent pageTitle={pageTitle} pageDescription={pageDescription} path={path} /> |
57 | 56 | </head> |
58 | 57 | <body |
59 | 58 | itemtype="http://schema.org/Person" |
60 | | - class="min-h-full overflow-y-auto font-sans leading-6 [font-smoothing:antialiased] bg-page-offset md:flex md:justify-center print:bg-white print:block" |
| 59 | + class="h-auto min-h-full overflow-y-auto text-content font-sans leading-6 [font-smoothing:antialiased] bg-page-offset md:flex md:justify-center print:bg-white print:block" |
61 | 60 | > |
62 | | - <div class="relative bg-primary-inverse mx-auto w-full max-w-4xl p-6 md:my-10 md:p-12 md:shadow-xl lg:my-14 lg:p-16 print:m-0 print:max-w-[21cm] print:p-[1cm] print:shadow-none"> |
| 61 | + <div class="relative bg-primary-inverse mx-auto w-full max-w-4xl p-6 md:my-10 md:p-12 md:shadow-xl lg:my-14 lg:p-16"> |
63 | 62 | <header |
64 | 63 | itemscope |
65 | 64 | itemref="resumeSubject" |
66 | | - class="relative border-b-2 border-trim/10 pb-6 mb-8 print:border-b print:border-trim/30 print:pb-4 print:mb-6" |
| 65 | + class="relative border-b-2 border-trim/10 pb-6 mb-8" |
67 | 66 | > |
68 | | - <h1 |
69 | | - itemprop="name" |
70 | | - class="text-4xl font-extrabold tracking-tight text-primary print:text-3xl" |
71 | | - > |
72 | | - <span itemprop="givenName">{resume.firstName}</span> |
73 | | - <span itemprop="familyName">{resume.lastName}</span> |
74 | | - </h1> |
75 | | - <div |
76 | | - class="text-xl font-medium text-danger-offset mt-1 tracking-wide print:text-lg" |
77 | | - itemprop="jobTitle" |
78 | | - > |
79 | | - {resume.title} |
| 67 | + <div class="md:absolute md:right-0 md:top-0"> |
| 68 | + <Controls /> |
| 69 | + </div> |
| 70 | + <Persona |
| 71 | + givenName={resume.firstName} |
| 72 | + familyName={resume.lastName} |
| 73 | + title={resume.title} |
| 74 | + /> |
| 75 | + <div class="mt-1!"> |
| 76 | + <Contact |
| 77 | + contactData={contactData} |
| 78 | + email={companyContact.email} |
| 79 | + /> |
80 | 80 | </div> |
81 | | - <dl class="flex gap-2 text-sm text-content-offset font-medium mt-6"> |
82 | | - <a |
83 | | - itemprop="email" |
84 | | - href={`mailto:${resume.email}`} |
85 | | - class="flex gap-2 hover:text-primary transition-colors duration-200" |
86 | | - > |
87 | | - <dt aria-label="email" class="text-primary-offset"> |
88 | | - <Icon icon="email-solid" color="content" size={4} /> |
89 | | - </dt> |
90 | | - <dd>{resume.email}</dd> |
91 | | - </a> |
92 | | - <a |
93 | | - id="locationWrapper" |
94 | | - itemprop="homeLocation" |
95 | | - itemscope |
96 | | - href={companyContact.mapLink} |
97 | | - class="flex gap-2 hover:text-primary transition-colors duration-200" |
98 | | - > |
99 | | - <dt aria-label="location" class="text-primary-offset"> |
100 | | - <Icon icon="location" color="content" size={6} /> |
101 | | - </dt> |
102 | | - <dd id="locationLabel" class="inline">{resumeLocation}</dd> |
103 | | - </a> |
104 | | - <a |
105 | | - id="telephoneWrapper" |
106 | | - itemprop="telephone" |
107 | | - itemscope |
108 | | - href={`tel:${companyContact.telephoneTollFree}`} |
109 | | - class="flex gap-2 hover:text-primary transition-colors duration-200" |
110 | | - > |
111 | | - <dt |
112 | | - aria-label="telephone" |
113 | | - class="text-primary-offset" |
114 | | - > |
115 | | - <Icon icon="telephone" color="content" size={6} /> |
116 | | - </dt> |
117 | | - <dd id="telephoneLabel" class="inline">{resumePhoneNumber}</dd> |
118 | | - </a> |
119 | | - </dl> |
120 | | - <ul class="md:absolute md:right-0 md:top-0 md:flex md:flex-row md:items-center md:gap-4 print:hidden text-content-offset"> |
121 | | - <li> |
122 | | - <a |
123 | | - class="inline-flex h-7 w-7 items-center justify-center hover:text-primary transition-colors duration-200" |
124 | | - href="pdf/resume.pdf" |
125 | | - title="Download PDF" |
126 | | - aria-label="Download PDF" |
127 | | - > |
128 | | - <Icon icon="download" color="content" size={7} /> |
129 | | - </a> |
130 | | - </li> |
131 | | - <li> |
132 | | - <button |
133 | | - class="inline-flex h-7 w-7 items-center justify-center appearance-none border-0 bg-transparent p-0 leading-none hover:text-primary transition-colors duration-200" |
134 | | - onclick="window.print()" |
135 | | - title="Print Resume" |
136 | | - aria-label="Print Resume" |
137 | | - > |
138 | | - <Icon icon="print" color="content" size={6} /> |
139 | | - </button> |
140 | | - </li> |
141 | | - </ul> |
142 | 81 | </header> |
143 | | - <main class="space-y-8 print:space-y-6"> |
144 | | - <section itemscope itemref="resumeSubject" itemtype="http://schema.org/ItemList"> |
145 | | - <h2 class="text-xs font-bold tracking-widest text-primary uppercase mb-3 border-b-2 border-trim/10 pb-2 print:border-trim/30 print:mb-2 print:pb-1">SUMMARY</h2> |
146 | | - <p itemprop="description" itemref="resumeSubject" class="text-content leading-relaxed print:text-sm"> |
147 | | - {resume.summary} |
148 | | - </p> |
149 | | - </section> |
| 82 | + <main class="space-y-8"> |
| 83 | + <div class=" mb-3 border-b-2 border-trim/10"> |
| 84 | + <Summary summary={resume.summary} /> |
| 85 | + </div> |
150 | 86 | <section id="experience"> |
151 | | - <h2 class="text-xs font-bold tracking-widest text-primary uppercase mb-4 border-b-2 border-trim/10 pb-2 print:border-trim/30 print:mb-3 print:pb-1">EXPERIENCE</h2> |
152 | | - <div class="space-y-8 print:space-y-5"> |
| 87 | + <h2 |
| 88 | + class="text-xs font-bold tracking-widest text-primary uppercase mb-4 border-b-2 border-trim/10" |
| 89 | + > |
| 90 | + Experience |
| 91 | + </h2> |
| 92 | + <div class="space-y-8"> |
153 | 93 | { |
154 | 94 | renderedClients.map(({ client, Content }: RenderedClient, index: number) => { |
155 | | - const location = splitLocation(client.data.location) |
156 | 95 | return ( |
157 | | - <div |
158 | | - id={`experienceItem-${index + 1}`} |
159 | | - class="flex flex-col gap-1.5" |
160 | | - itemprop="worksFor" |
161 | | - itemscope |
162 | | - itemref="resumeSubject" |
163 | | - itemtype="http://schema.org/Organization" |
164 | | - > |
165 | | - <div class="flex flex-col md:flex-row md:items-baseline md:justify-between"> |
166 | | - <h3 |
167 | | - id={`role-${index + 1}`} |
168 | | - class="text-xl font-bold text-content-active print:text-lg" |
169 | | - itemprop="Role" |
170 | | - itemref={`experienceItem-${index + 1}`} |
171 | | - itemscope |
172 | | - itemtype="https://schema.org/EmployeeRole" |
173 | | - > |
174 | | - <span itemprop="roleName"> |
175 | | - {client.data.role ?? client.data.businessType ?? client.data.displayName} |
176 | | - </span> |
177 | | - </h3> |
178 | | - <div class="text-sm font-medium text-content-offset mt-0.5 md:mt-0 flex gap-1.5 items-center"> |
179 | | - <time |
180 | | - itemprop="startDate" |
181 | | - itemtype="http://schema.org/startDate" |
182 | | - datetime={formatDateContent(client.data.startDate)} |
183 | | - > |
184 | | - {formatMonthYear(client.data.startDate)} |
185 | | - </time> |
186 | | - <span class="text-trim/50">—</span> |
187 | | - <time |
188 | | - itemprop="endDate" |
189 | | - itemtype="http://schema.org/endDate" |
190 | | - datetime={formatDateContent(client.data.endDate)} |
191 | | - > |
192 | | - {formatMonthYear(client.data.endDate)} |
193 | | - </time> |
194 | | - </div> |
195 | | - </div> |
196 | | - <div class="text-base font-semibold text-primary-offset flex flex-wrap items-center gap-x-2 gap-y-1 print:text-sm"> |
197 | | - <span itemprop="legalName">{client.data.displayName}</span> |
198 | | - {client.data.location && ( |
199 | | - <> |
200 | | - <span class="text-trim/30 select-none">•</span> |
201 | | - <a |
202 | | - class="inline-flex items-center gap-1 hover:text-primary transition-colors text-content-offset font-medium" |
203 | | - href={client.data.website ?? ''} |
204 | | - itemprop="location" |
205 | | - itemscope |
206 | | - itemtype="http://schema.org/PostalAddress" |
207 | | - > |
208 | | - <Icon icon="location" color="content" size={6} /> |
209 | | - <span> |
210 | | - <span itemprop="addressLocality">{location.locality}</span> |
211 | | - {location.region && ( |
212 | | - <>, <span itemprop="addressRegion">{location.region}</span></> |
213 | | - )} |
214 | | - </span> |
215 | | - </a> |
216 | | - </> |
217 | | - )} |
218 | | - </div> |
219 | | - <div class="experienceDetailContent mt-3" itemprop="description"> |
220 | | - <Content components={{ List, ListItem }} /> |
221 | | - </div> |
222 | | - </div> |
| 96 | + <ExperienceCard |
| 97 | + index={index} |
| 98 | + client={client} |
| 99 | + Content={Content} |
| 100 | + /> |
223 | 101 | ) |
224 | 102 | }) |
225 | 103 | } |
226 | 104 | </div> |
227 | 105 | </section> |
228 | | - <section class="mt-8 print:mt-6" itemscope itemref="resumeSubject" itemtype="http://schema.org/ItemList"> |
229 | | - <h2 class="text-xs font-bold tracking-widest text-primary uppercase mb-4 border-b-2 border-trim/10 pb-2 print:border-trim/30 print:mb-3 print:pb-1">SKILLS</h2> |
230 | | - <div class="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4 print:gap-y-3"> |
231 | | - { |
232 | | - resume.skills.map((skill: (typeof resume.skills)[number]) => ( |
233 | | - <div |
234 | | - class="flex flex-col" |
235 | | - itemref="resumeSubject" |
236 | | - itemscope |
237 | | - itemprop="knowsAbout" |
238 | | - itemtype="http://schema.org/knowsAbout" |
239 | | - > |
240 | | - <h3 class="font-bold text-content-active text-sm mb-1">{skill.lead}</h3> |
241 | | - <p class="text-sm text-content-offset leading-relaxed print:text-xs">{skill.text}</p> |
242 | | - </div> |
243 | | - )) |
244 | | - } |
| 106 | + <section class="mt-8" itemscope itemref="resumeSubject" itemtype="http://schema.org/ItemList"> |
| 107 | + <h2 class="text-xs font-bold tracking-widest text-primary uppercase mb-4 border-b-2 border-trim/10 pb-2">Skills</h2> |
| 108 | + <div class="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4"> |
| 109 | + <Skills skills={resume.skills} /> |
245 | 110 | </div> |
246 | 111 | </section> |
247 | 112 | <section |
248 | 113 | id="languages" |
249 | | - class="mt-8 print:mt-6" |
| 114 | + class="mt-8" |
250 | 115 | itemscope |
251 | 116 | itemref="resumeSubject" |
252 | 117 | itemtype="http://schema.org/ItemList" |
253 | 118 | > |
254 | | - <h2 class="text-xs font-bold tracking-widest text-primary uppercase mb-4 border-b-2 border-trim/10 pb-2 print:border-trim/30 print:mb-3 print:pb-1">LANGUAGES</h2> |
255 | | - <ul class="flex flex-wrap gap-4 text-sm font-medium text-content-offset print:text-xs"> |
| 119 | + <h2 class="text-xs font-bold tracking-widest text-primary uppercase mb-4 border-b-2 border-trim/10 pb-2">Languages</h2> |
| 120 | + <ul class="flex flex-wrap gap-4 text-sm font-medium text-content-offset"> |
256 | 121 | { |
257 | 122 | resume.languages.map((language: (typeof resume.languages)[number]) => ( |
258 | 123 | <li |
|
0 commit comments