Skip to content

Commit 7da8683

Browse files
committed
Merged CV
1 parent cc834b4 commit 7da8683

37 files changed

Lines changed: 2718 additions & 195 deletions

Chris Tham resume 2021-03-21.pdf

148 KB
Binary file not shown.

conductor/resume_update_plan.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Resume Update Implementation Plan
2+
3+
## Objective
4+
Update the `src/content/` collections and `src/pages/index.md` based on the provided resume OCR, aligning dates, roles, and descriptions.
5+
6+
## Key Files & Context
7+
- `src/content/education/` (add Macquarie, SIA; modify USYD; delete UNSW)
8+
- `src/content/work/` (update existing entries, add USYD tutor, set `tfnsw.md` as consulting)
9+
- `src/pages/index.md` (add Profile summary and Papers/Conferences)
10+
11+
## Implementation Steps
12+
13+
### 1. Education Updates
14+
- **Create** `src/content/education/macquarie.md`: Master of Applied Finance, Macquarie University (1994). Add awards (Institute of Bankers Prize, "The Institute Prize").
15+
- **Create** `src/content/education/sia.md`: Graduate Diploma, Securities Institute of Australia (1992).
16+
- **Update** `src/content/education/usyd.md`: Change to Bachelor of Science (1st Class Honours and University Medal), 1988. Add scholarships.
17+
- **Delete** `src/content/education/unsw.md` as requested.
18+
19+
### 2. Work History Updates
20+
- **`hellotham.md`**: Update role to "Principal Consultant and Director", 2016-Present. Mention providing strategic consulting services.
21+
- **`tfnsw.md`**: Keep separate, but set `type: consulting` and `startyear: 2016`. Incorporate the detailed bullet points from the resume (AI/ML dashboards, chatbot PoC, iOS app PoC, multi-channel framework, business plans, etc.).
22+
- **`broadspectrum.md`**: Align roles, dates (2011-2016), and bullet points with the resume (Strategy Consultant, Exec Manager Architecture & Design).
23+
- **`thorogood.md`**: Verify/align 2011 consultant role and bullets.
24+
- **`ing.md`**: Set dates to 2008 and verify bullet points.
25+
- **`nab.md`**: Update dates to 2005-2007. Break out details for Head of Distribution (2005), Head of Retail Banking (2006), and Strategy Consultant (2007).
26+
- **`mlc.md`**: Update dates to 1998-2004 and align bullet points.
27+
- **`hp.md`**: Update dates to 1995-1998. Update description (Boral data centre consolidation, etc.).
28+
- **`ncr.md`**: Update dates to 1992-1995. Update description (Telstra, Rockmans, Franklins, St. George).
29+
- **`sbv.md`**: Update dates to 1990-1992.
30+
- **`optech.md`**: Update dates to 1988-1990.
31+
- **`bain.md`**: Update dates to 1986-1988.
32+
- **Create `usyd-tutor.md`**: Tutor, University of Sydney, 1987.
33+
34+
### 3. Homepage Updates
35+
- **`src/pages/index.md`**: Integrate the "Profile" summary from the resume into the top content.
36+
- **`src/pages/index.md`**: Add a new section for "Papers / Conferences" and list the items from the resume.
37+
38+
## Verification & Testing
39+
- Run `pnpm run build` to ensure the content collections build without errors and all frontmatter is valid according to `content.config.ts`.
40+
- Visually verify changes using `pnpm run dev` if needed.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "spotlite",
33
"description": "Astro Personal Web Site Template",
44
"type": "module",
5-
"version": "2.2.5",
5+
"version": "2.2.6",
66
"scripts": {
77
"dev": "astro dev",
88
"clean": "rm -rf node_modules .astro coverage dist",

public/cv.pdf

13.4 KB
Binary file not shown.

scripts/generate-pdf.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ const configFile = path.join(rootDir, 'src/config.json')
1616
const outputPath = path.join(rootDir, 'public/cv.pdf')
1717
const stylesheetPath = path.join(rootDir, 'scripts/pdf-theme.css')
1818

19+
const formatDateRange = (start, end) => {
20+
if (!end) return `${start} — Present`
21+
if (start === end) return `${start}`
22+
return `${start}${end}`
23+
}
24+
1925
async function generatePdf() {
2026
console.log('Starting PDF generation...')
2127

@@ -74,14 +80,14 @@ async function generatePdf() {
7480
// Inject collection data if it's the work or education page
7581
if (pageId === 'work' && workItems.length > 0) {
7682
const workMd = workItems.map(item => {
77-
const dateStr = `${item.data.startyear}${item.data.endyear || 'Present'}`
83+
const dateStr = formatDateRange(item.data.startyear, item.data.endyear)
7884
const typeStr = item.data.type === 'consulting' ? ' (Consulting)' : ''
7985
return `### ${item.data.role}${typeStr}\n**${item.data.company}** | *${dateStr}*\n\n${item.content}`
8086
}).join('\n\n')
8187
body = body + '\n\n' + workMd
8288
} else if (pageId === 'education' && educationItems.length > 0) {
8389
const eduMd = educationItems.map(item => {
84-
const dateStr = `${item.data.startyear}${item.data.endyear || 'Present'}`
90+
const dateStr = formatDateRange(item.data.startyear, item.data.endyear)
8591
return `### ${item.data.degree}\n**${item.data.institution}** | *${dateStr}*\n\n${item.content}`
8692
}).join('\n\n')
8793
body = body + '\n\n' + eduMd

src/components/d3timeline.astro

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const timelineData = processTimelineData(workEntries, educationEntries)
2121

2222
<script>
2323
import * as d3 from 'd3'
24-
import type { TimelineEntry } from '../utils/timeline'
24+
import { type TimelineEntry, formatDateRange } from '../utils/timeline'
2525

2626
const setupTimeline = () => {
2727
const container = document.getElementById('timeline-container')
@@ -46,7 +46,7 @@ const timelineData = processTimelineData(workEntries, educationEntries)
4646

4747
const margin = isVertical
4848
? { top: 20, right: 20, bottom: 40, left: 100 }
49-
: { top: 20, right: 30, bottom: 40, left: 40 }
49+
: { top: 20, right: 30, bottom: 40, left: 150 }
5050

5151
const innerWidth = width - margin.left - margin.right
5252
const innerHeight = height - margin.top - margin.bottom
@@ -101,22 +101,27 @@ const timelineData = processTimelineData(workEntries, educationEntries)
101101
const xScale = d3.scaleLinear().domain([minYear, maxYear]).range([0, innerWidth])
102102

103103
const yScale = d3
104-
.scaleBand<string>()
105-
.domain(data.map((d) => d.title))
104+
.scaleBand<number>()
105+
.domain(d3.range(data.length))
106106
.range([0, innerHeight])
107107
.padding(0.2)
108108

109109
const xAxis = d3.axisBottom(xScale).tickFormat(d3.format('d'))
110+
const yAxis = d3.axisLeft(yScale).tickFormat((i) => data[i].organization || data[i].title)
110111

111112
svg.append('g').attr('transform', `translate(0,${innerHeight})`).call(xAxis)
113+
svg.append('g').call(yAxis).selectAll('text').attr('class', 'text-[10px] fill-current')
112114

113115
svg
114116
.selectAll('rect')
115117
.data(data)
116118
.join('rect')
117119
.attr('x', (d) => xScale(d.startYear))
118-
.attr('y', (d) => yScale(d.title) || 0)
119-
.attr('width', (d) => xScale(d.endYear) - xScale(d.startYear))
120+
.attr('y', (_d, i) => yScale(i) || 0)
121+
.attr('width', (d) => {
122+
const end = d.startYear === d.endYear && !d.isOngoing ? d.endYear + 1 : d.endYear
123+
return xScale(end) - xScale(d.startYear)
124+
})
120125
.attr('height', yScale.bandwidth())
121126
.attr('fill', (d) =>
122127
d.isOngoing ? `url(#grad-h-${d.type})` : colorMap[d.type] || '#ccc'
@@ -130,7 +135,7 @@ const timelineData = processTimelineData(workEntries, educationEntries)
130135
<p class="text-primary leading-tight">${d.organization}</p>
131136
<div class="mt-2 pt-2 border-t border-primary/20 flex justify-between items-center">
132137
<span class="text-xs text-secondary uppercase tracking-wider">${d.type}</span>
133-
<span class="font-bold text-accent">${d.startYear} - ${d.isOngoing ? 'Present' : d.endYear}</span>
138+
<span class="font-bold text-accent">${formatDateRange(d.startYear, d.isOngoing ? undefined : d.endYear)}</span>
134139
</div>
135140
</div>
136141
`)
@@ -167,23 +172,35 @@ const timelineData = processTimelineData(workEntries, educationEntries)
167172
const yScale = d3.scaleLinear().domain([minYear, maxYear]).range([0, innerHeight])
168173

169174
const xScale = d3
170-
.scaleBand<string>()
171-
.domain(data.map((d) => d.title))
175+
.scaleBand<number>()
176+
.domain(d3.range(data.length))
172177
.range([0, innerWidth])
173178
.padding(0.2)
174179

175180
const yAxis = d3.axisLeft(yScale).tickFormat(d3.format('d'))
181+
const xAxis = d3.axisBottom(xScale).tickFormat((i) => data[i].organization || data[i].title)
176182

177183
svg.append('g').call(yAxis)
184+
svg
185+
.append('g')
186+
.attr('transform', `translate(0,${innerHeight})`)
187+
.call(xAxis)
188+
.selectAll('text')
189+
.attr('class', 'text-[8px] fill-current')
190+
.attr('transform', 'rotate(-45)')
191+
.style('text-anchor', 'end')
178192

179193
svg
180194
.selectAll('rect')
181195
.data(data)
182196
.join('rect')
183-
.attr('x', (d) => xScale(d.title) || 0)
197+
.attr('x', (_d, i) => xScale(i) || 0)
184198
.attr('y', (d) => yScale(d.startYear))
185199
.attr('width', xScale.bandwidth())
186-
.attr('height', (d) => yScale(d.endYear) - yScale(d.startYear))
200+
.attr('height', (d) => {
201+
const end = d.startYear === d.endYear && !d.isOngoing ? d.endYear + 1 : d.endYear
202+
return yScale(end) - yScale(d.startYear)
203+
})
187204
.attr('fill', (d) =>
188205
d.isOngoing ? `url(#grad-v-${d.type})` : colorMap[d.type] || '#ccc'
189206
)
@@ -196,7 +213,7 @@ const timelineData = processTimelineData(workEntries, educationEntries)
196213
<p class="text-primary leading-tight">${d.organization}</p>
197214
<div class="mt-2 pt-2 border-t border-primary/20 flex justify-between items-center">
198215
<span class="text-xs text-secondary uppercase tracking-wider">${d.type}</span>
199-
<span class="font-bold text-accent">${d.startYear} - ${d.isOngoing ? 'Present' : d.endYear}</span>
216+
<span class="font-bold text-accent">${formatDateRange(d.startYear, d.isOngoing ? undefined : d.endYear)}</span>
200217
</div>
201218
</div>
202219
`)

src/components/education.astro

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
import { getCollection } from 'astro:content'
33
import { Image } from 'astro:assets'
4+
import { formatDateRange } from '../utils/timeline'
45
56
let education = await getCollection('education')
67
education = education.sort((a, b) => {
@@ -24,14 +25,13 @@ education = education.sort((a, b) => {
2425
href={`${import.meta.env.BASE_URL}education/${item.id}/`}
2526
class='group p-2 rounded-xl flex gap-4 transition -m-2 hover:bg-heavenlyPink/50 focus-ring dark:hover:bg-grapeade/30'
2627
>
27-
<div class='mt-1 rounded-full flex flex-none h-10 w-10 ring-1 ring-opalGray/20 shadow-md items-center justify-center relative dark:border dark:border-border/50 dark:bg-blackBeauty dark:ring-0'>
28+
<div class='mt-1 flex flex-none w-24 h-10 ring-1 ring-opalGray/20 shadow-md items-center justify-center relative dark:border dark:border-border/50 dark:bg-blackBeauty dark:ring-0'>
2829
<Image
2930
src={item.data.image}
3031
alt={item.data.institution}
31-
width={64}
3232
height={64}
3333
loading='lazy'
34-
class='h-8 w-8 object-cover'
34+
class='h-8 w-auto object-contain'
3535
/>
3636
</div>
3737
<dl class='flex flex-auto flex-wrap gap-x-2'>
@@ -44,9 +44,9 @@ education = education.sort((a, b) => {
4444
<dt class='sr-only'>Date</dt>
4545
<dd
4646
class='text-xs text-secondary ml-auto'
47-
aria-label={`${item.data.startyear} to ${item.data.endyear || 'Present'}`}
47+
aria-label={formatDateRange(item.data.startyear, item.data.endyear)}
4848
>
49-
{item.data.startyear}{item.data.endyear || 'Present'}
49+
{formatDateRange(item.data.startyear, item.data.endyear)}
5050
</dd>
5151
</dl>
5252
</a>

src/components/work.astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
import { getCollection } from 'astro:content'
33
import { Image } from 'astro:assets'
4+
import { formatDateRange } from '../utils/timeline'
45
56
let work = await getCollection('work')
67
work = work.sort((a, b) => {
@@ -47,9 +48,9 @@ work = work.sort((a, b) => {
4748
<dt class='sr-only'>Date</dt>
4849
<dd
4950
class='text-xs text-secondary ml-auto'
50-
aria-label={`${job.data.startyear} to ${job.data.endyear || 'Present'}`}
51+
aria-label={formatDateRange(job.data.startyear, job.data.endyear)}
5152
>
52-
{job.data.startyear}{job.data.endyear || 'Present'}
53+
{formatDateRange(job.data.startyear, job.data.endyear)}
5354
</dd>
5455
</dl>
5556
</a>

src/content/education/macquarie.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
institution: Macquarie University
3+
degree: Master of Applied Finance
4+
startyear: 1994
5+
endyear: 1994
6+
image: ./mq.svg
7+
---
8+
9+
Awarded:
10+
- Australian Institute of Bankers Prize for Management of Financial Institutions
11+
- Australian Institute of Bankers "The Institute Prize" (for graduating top of class)

0 commit comments

Comments
 (0)