Skip to content

Commit

Permalink
feat: Fix design on work page
Browse files Browse the repository at this point in the history
  • Loading branch information
kiosion committed Jan 25, 2024
1 parent dce0ac9 commit fb1c634
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 75 deletions.
97 changes: 70 additions & 27 deletions svelte-app/src/components/about/timeline-item.svelte
Original file line number Diff line number Diff line change
@@ -1,59 +1,102 @@
<script lang="ts">
import BulletPoint from '$components/bullet-point.svelte';
import { displayMonthDuration, displayRange } from '$lib/date';
import PortableText from '$components/portable-text/portable-text.svelte';
import type { WorkTimelineItem } from '$types';
export let title: string | undefined, body: WorkTimelineItem['body'], date: string;
export let title: WorkTimelineItem['subtitle'],
body: WorkTimelineItem['body'],
range: WorkTimelineItem['range'],
last = false;
</script>

<div class="item">
<div>
<BulletPoint />
<span>
<h2>{title}</h2>
<p>{date}</p>
</span>
<div class:last class="item">
<span class="bullet" />
<div class="content">
<h3>{title}</h3>
<p>
{$displayRange(range.start, range.end)} &bull; {$displayMonthDuration(
range.start,
range.end
)}
</p>
{#if body}
<div class="body">
<PortableText text={body} />
</div>
{/if}
</div>

{#if body}
<div class="body">
<PortableText text={body} />
</div>
{/if}
</div>

<style lang="scss">
$bulletTopGap: 12px;
$lineTopGap: 16px;
$bulletWidth: 6px;
$lineWidth: 2px;
.item {
@apply flex flex-col items-start justify-start;
@apply relative flex flex-row items-start justify-start gap-x-6 pb-5 pl-3;
&.last {
@apply pb-0;
}
}
h2 {
.bullet {
@apply block flex-shrink-0 rounded-full bg-dark/40;
margin-top: $bulletTopGap;
width: $bulletWidth;
height: $bulletWidth;
}
h3 {
@apply text-lg font-bold text-dark transition-colors;
}
div {
@apply flex w-full flex-row items-center justify-start gap-x-2;
.content {
.last & {
&:before {
@apply hidden;
}
}
&:before {
@apply absolute bg-dark/20;
$bulletSpaceFromTop: $bulletTopGap + $bulletWidth;
span {
@apply flex w-full flex-row items-center justify-between text-base;
content: '';
top: #{$bulletSpaceFromTop + $lineTopGap};
left: #{$bulletWidth * 2 + $lineWidth};
height: calc(100% - #{($bulletSpaceFromTop + $lineTopGap) + calc($lineTopGap / 2)});
width: $lineWidth;
}
p {
@apply text-right font-mono text-sm text-dark/80 transition-colors;
@apply font-mono text-sm text-dark/80 transition-colors;
}
}
.body {
@apply -mt-1 pl-8 text-base;
.body {
@apply -mb-4;
}
}
:global(.dark) {
h2 {
h3 {
@apply text-white;
}
div {
.bullet {
@apply bg-white/40;
}
.content {
&:before {
@apply bg-white/20;
}
p {
@apply text-light/80;
}
Expand Down
83 changes: 37 additions & 46 deletions svelte-app/src/components/about/timeline-section.svelte
Original file line number Diff line number Diff line change
@@ -1,73 +1,64 @@
<script lang="ts">
import { derived } from 'svelte/store';
import { displayMonthDuration, displayRange } from '$lib/date';
import { currentLang, t } from '$i18n';
import TimelineItem from './timeline-item.svelte';
import TimelineItem from '$components/about/timeline-item.svelte';
import type { WorkTimelineItem } from '$types';
export let section: WorkTimelineItem[];
const title = section[0].title;
const dateDisplay = derived([currentLang, t], ([currentLang, t]) => {
return (start: string, end: string | undefined) => {
try {
const startDate = new Date(start),
endDate = end ? new Date(end) : undefined;
if (!endDate) {
return `${new Intl.DateTimeFormat(currentLang, {
month: 'short',
year: 'numeric'
}).format(startDate)} - ${t('present')}`;
}
return `${new Intl.DateTimeFormat(currentLang, {
month: 'short',
year: 'numeric'
}).format(startDate)} - ${new Intl.DateTimeFormat(currentLang, {
month: 'short',
year: 'numeric'
}).format(endDate)}`;
} catch (_) {
return t('Invalid date');
}
const title = section[0].title,
totalRange = {
start: section[section.length - 1].range.start,
end: section[0].range.end
};
});
</script>

<section>
<h1>{title}</h1>

<div>
{#each section as item}
<TimelineItem
title={item.subtitle}
body={item.body}
date={$dateDisplay(item.range.start, item.range.end)}
/>
{/each}
<h2>{title}</h2>
<p>
{$displayRange(totalRange.start, totalRange.end)} &bull; {$displayMonthDuration(
totalRange.start,
totalRange.end
)}
</p>
</div>

{#each section as item, i}
<TimelineItem
title={item.subtitle}
body={item.body}
range={item.range}
last={i === section.length - 1}
/>
{/each}
</section>

<style lang="scss">
h1 {
@apply mb-3 font-code text-2xl font-bold text-dark transition-colors;
h2 {
@apply pb-1 text-xl font-bold text-dark transition-colors;
}
p {
@apply font-mono text-sm text-dark/80 transition-colors;
}
div {
@apply pb-4;
}
section {
@apply my-6;
div {
@apply flex flex-col;
}
}
:global(.dark) {
h1 {
h2 {
@apply text-white;
}
p {
@apply text-light/80;
}
}
</style>
6 changes: 5 additions & 1 deletion svelte-app/src/languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
"present": "present",
"refresh the page": "refresh the page",
"{length} min read": "{length} min read",
"{months} months": "{months} months",
"{month} month": "{month} month",
"{stars} stars": "{stars} stars",
"{views} views": "{views} views"
"{views} views": "{views} views",
"{years} years": "{years} years",
"{year} year": "{year} year"
}
6 changes: 5 additions & 1 deletion svelte-app/src/languages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
"present": "présent",
"refresh the page": "rafraîchir la page",
"{length} min read": "{length} minute de lecture",
"{month} month": "{month} mois",
"{month} months": "{month} mois",
"{stars} stars": "{stars} étoiles",
"{views} views": "{views} vues"
"{views} views": "{views} vues",
"{year} year": "{year} an",
"{year} years": "{year} ans"
}
83 changes: 83 additions & 0 deletions svelte-app/src/lib/date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* eslint-disable func-call-spacing */
import { derived } from 'svelte/store';

import { currentLang, t } from '$i18n';

export const displayRange = derived([currentLang, t], ([currentLang, t]) => {
return (start: string, end: string | undefined) => {
try {
const startDate = new Date(start),
endDate = end ? new Date(end) : undefined;

if (!endDate) {
return `${new Intl.DateTimeFormat(currentLang, {
month: 'short',
year: 'numeric'
}).format(startDate)} - ${t('present')}`;
}

return `${new Intl.DateTimeFormat(currentLang, {
month: 'short',
year: 'numeric'
}).format(startDate)} - ${new Intl.DateTimeFormat(currentLang, {
month: 'short',
year: 'numeric'
}).format(endDate)}`;
} catch (_) {
return t('Invalid date');
}
};
});

export const displayMonthDuration = derived<
typeof t,
(startDate?: string | Date, endDate?: string | Date) => string
>(t, (t) => {
return (startDate?: string | Date, endDate?: string | Date) => {
if (!startDate) {
return t('{month} month', { month: 1 });
}

const start = new Date(startDate),
end = endDate ? new Date(endDate) : new Date();

let years = end.getFullYear() - start.getFullYear();
let months = end.getMonth() - start.getMonth();

// Adjust for cases where the end month is earlier in the year than the start month
if (months < 0) {
years--;
months += 12; // Add the months that have passed in the current year
}

// Consolidate total duration into years and months
years += Math.floor(months / 12);
months %= 12;

let yearString = '',
monthString = '';

if (years > 0) {
if (years === 1) {
yearString = t('{year} year', { year: years });
} else {
yearString = t('{year} years', { year: years });
}
}

if (months > 0) {
if (months === 1) {
monthString = t('{month} month', { month: months });
} else {
monthString = t('{month} months', { month: months });
}
}

// Handle the case where the difference is less than one month
if (years > 0 && months > 0) {
monthString = t('{month} month', { month: 1 });
}

return `${yearString}${yearString && monthString ? ' ' : ''}${monthString}`;
};
});

0 comments on commit fb1c634

Please sign in to comment.