add basic layout of project-timeline-item (#44)
Co-authored-by: Bury <agnieszka.bury@capgemini.com>
This commit is contained in:
parent
359d7669b1
commit
33d22dc320
11 changed files with 882 additions and 686 deletions
13
package-lock.json
generated
13
package-lock.json
generated
|
|
@ -40,6 +40,7 @@
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
"eslint-plugin-simple-import-sort": "8.0.0",
|
"eslint-plugin-simple-import-sort": "8.0.0",
|
||||||
"iconify-icon-names": "1.0.1",
|
"iconify-icon-names": "1.0.1",
|
||||||
|
"locales-ts": "1.0.0",
|
||||||
"postcss": "8.4.19",
|
"postcss": "8.4.19",
|
||||||
"prettier": "2.7.1",
|
"prettier": "2.7.1",
|
||||||
"tailwindcss": "3.2.4",
|
"tailwindcss": "3.2.4",
|
||||||
|
|
@ -5809,6 +5810,12 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/locales-ts": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/locales-ts/-/locales-ts-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-8AH3T6AHmNUQTkmpstwdOUlt9+4N3gPavS2OZCGDi2Fl/HAbkfmIbtL2DG3AgGEY+u+7fw/VdDqDjKSeF/e3sQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
|
|
@ -14715,6 +14722,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"locales-ts": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/locales-ts/-/locales-ts-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-8AH3T6AHmNUQTkmpstwdOUlt9+4N3gPavS2OZCGDi2Fl/HAbkfmIbtL2DG3AgGEY+u+7fw/VdDqDjKSeF/e3sQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"locate-path": {
|
"locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
"eslint-plugin-simple-import-sort": "8.0.0",
|
"eslint-plugin-simple-import-sort": "8.0.0",
|
||||||
"iconify-icon-names": "1.0.1",
|
"iconify-icon-names": "1.0.1",
|
||||||
|
"locales-ts": "1.0.0",
|
||||||
"postcss": "8.4.19",
|
"postcss": "8.4.19",
|
||||||
"prettier": "2.7.1",
|
"prettier": "2.7.1",
|
||||||
"tailwindcss": "3.2.4",
|
"tailwindcss": "3.2.4",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
export interface Props {
|
export interface Props {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string | string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const { label, value } = Astro.props;
|
const { label, value } = Astro.props;
|
||||||
|
|
|
||||||
17
src/components/atoms/timestamp.astro
Normal file
17
src/components/atoms/timestamp.astro
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
import Typography from '@/atoms/typography.astro';
|
||||||
|
|
||||||
|
export interface Props extends astroHTML.JSX.HTMLAttributes {
|
||||||
|
startDate: Date;
|
||||||
|
endDate: Date | null;
|
||||||
|
locale: string;
|
||||||
|
translationForNow: string;
|
||||||
|
}
|
||||||
|
const { startDate, endDate, locale, translationForNow, ...props } = Astro.props;
|
||||||
|
const getFormattedDate = (date: Date): string =>
|
||||||
|
new Intl.DateTimeFormat(locale, { month: 'long' }).format(date).concat(' ', date.getFullYear().toString());
|
||||||
|
---
|
||||||
|
|
||||||
|
<Typography variant="item-subtitle" class:list={[props.class]}>
|
||||||
|
{getFormattedDate(startDate).concat(' - ', endDate ? getFormattedDate(endDate) : translationForNow)}
|
||||||
|
</Typography>
|
||||||
82
src/components/organisms/project-timeline-item.astro
Normal file
82
src/components/organisms/project-timeline-item.astro
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
---
|
||||||
|
import { Image } from '@astrojs/image/components';
|
||||||
|
|
||||||
|
import IconButton from '@/atoms/icon-button.astro';
|
||||||
|
import LabelledValue from '@/atoms/labelled-value.astro';
|
||||||
|
import Tag from '@/atoms/tag.astro';
|
||||||
|
import Timestamp from '@/atoms/timestamp.astro';
|
||||||
|
import Typography from '@/atoms/typography.astro';
|
||||||
|
import type { I18n } from '@/types/i18n';
|
||||||
|
import type { Project } from '@/types/portfolio-section';
|
||||||
|
|
||||||
|
export interface Props extends astroHTML.JSX.HTMLAttributes {
|
||||||
|
value: Project;
|
||||||
|
i18n: I18n;
|
||||||
|
}
|
||||||
|
const { value, i18n, ...props } = Astro.props;
|
||||||
|
const ProjectTimelineItem = 'div';
|
||||||
|
|
||||||
|
const setLabelValue = (val: string | string[]) =>
|
||||||
|
Array.isArray(val) ? val.map((v, id) => (id !== val.length - 1 ? v.concat(', ') : v)) : val;
|
||||||
|
---
|
||||||
|
|
||||||
|
<ProjectTimelineItem class:list={[props.className]}>
|
||||||
|
<div class:list={['flex', 'flex-col', 'sm:grid', 'overflow-hidden', 'grid-cols-[120px_minmax(200px,_1fr)]', 'gap-2']}>
|
||||||
|
<Image
|
||||||
|
class:list={['rounded-lg', 'object-cover', 'max-w-[120px]', 'm-0', 'overflow-hidden', 'sm:block', 'hidden']}
|
||||||
|
src={value.image}
|
||||||
|
aspectRatio="1/1"
|
||||||
|
alt={''}
|
||||||
|
format="webp"
|
||||||
|
/>
|
||||||
|
<div class:list={['col-start-2', 'col-span-2', 'sm:mx-6']}>
|
||||||
|
<div class:list={['flex', 'justify-between']}>
|
||||||
|
<Typography variant="item-title">{value.name}</Typography>
|
||||||
|
<div class:list={['fixed', 'top-3', 'right-3', 'md:flex', 'md:flex-wrap', 'gap-3', '[&>a]:my-2']}>
|
||||||
|
{value.socials?.map(({ icon, url }) => <IconButton icon={icon} href={url} target="_blank" size="small" />)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Timestamp
|
||||||
|
startDate={value.startDate}
|
||||||
|
endDate={value.endDate}
|
||||||
|
locale={i18n.locale}
|
||||||
|
translationForNow={i18n.translations.now}
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
class:list={['rounded-lg', 'object-cover', 'my-2', 'max-w-[120px]', 'sm:block', 'sm:hidden']}
|
||||||
|
src={value.image}
|
||||||
|
aspectRatio="1/1"
|
||||||
|
alt={''}
|
||||||
|
format="webp"
|
||||||
|
/>
|
||||||
|
<div class:list={['flex', 'md:gap-3', 'md:flex-row', 'flex-col', 'my-4']}>
|
||||||
|
<div class:list={['md:w-2/6']}>
|
||||||
|
{
|
||||||
|
value.details
|
||||||
|
.slice(0, Math.round(value.details.length / 2))
|
||||||
|
.map((d) => <LabelledValue label={d.label} value={setLabelValue(d.value)} />)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
value.details
|
||||||
|
.slice(Math.round(value.details.length / 2))
|
||||||
|
.map((d) => <LabelledValue label={d.label} value={setLabelValue(d.value)} />)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class:list={['col-start-1 col-span-3']}>
|
||||||
|
<Typography variant="paragraph">{value.description}</Typography>
|
||||||
|
</div>
|
||||||
|
<div class:list={['flex', 'gap-3', 'flex-wrap', 'sm:flex-nowrap', 'mt-6']}>
|
||||||
|
{
|
||||||
|
value.tags.map((t) => (
|
||||||
|
<Tag name={t.icon} color={t.iconColor}>
|
||||||
|
{t.name}
|
||||||
|
</Tag>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ProjectTimelineItem>
|
||||||
1368
src/data.ts
1368
src/data.ts
File diff suppressed because it is too large
Load diff
|
|
@ -11,7 +11,7 @@ import getObjectKeys from '@/utils/getObjectKeys';
|
||||||
|
|
||||||
import data from '../data';
|
import data from '../data';
|
||||||
|
|
||||||
const { seo, ...dataWithoutSeo } = data;
|
const { seo, i18n, ...dataWithoutSeoAndI18n } = data;
|
||||||
---
|
---
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
|
@ -29,8 +29,8 @@ const { seo, ...dataWithoutSeo } = data;
|
||||||
<div class="absolute z-40 -right-2">
|
<div class="absolute z-40 -right-2">
|
||||||
<Sidebar className="hidden xl:flex fixed">
|
<Sidebar className="hidden xl:flex fixed">
|
||||||
{
|
{
|
||||||
getObjectKeys(dataWithoutSeo).map((key) => {
|
getObjectKeys(dataWithoutSeoAndI18n).map((key) => {
|
||||||
const sectionData = dataWithoutSeo[key];
|
const sectionData = dataWithoutSeoAndI18n[key];
|
||||||
return (
|
return (
|
||||||
sectionData && (
|
sectionData && (
|
||||||
<SidebarItem
|
<SidebarItem
|
||||||
|
|
|
||||||
67
src/pages/playground/projects-timeline.astro
Normal file
67
src/pages/playground/projects-timeline.astro
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
---
|
||||||
|
import ProjectTimelineItem from '@/organisms/project-timeline-item.astro';
|
||||||
|
import type { I18n } from '@/types/i18n';
|
||||||
|
import type { Project } from '@/types/portfolio-section';
|
||||||
|
|
||||||
|
const project: Project = {
|
||||||
|
name: 'Golden Bulls',
|
||||||
|
image: import('@/assets/portfolio/project-1.jpeg'),
|
||||||
|
startDate: new Date('2020-03'),
|
||||||
|
endDate: null,
|
||||||
|
details: [
|
||||||
|
{ label: 'Team size', value: '1 person' },
|
||||||
|
{ label: 'Company', value: 'None' },
|
||||||
|
{ label: 'My role', value: ['Front-end Developer', 'Designer'] },
|
||||||
|
{ label: 'Category', value: ['Web app', 'Open source'] },
|
||||||
|
],
|
||||||
|
description:
|
||||||
|
'In tristique vulputate augue vel egestas. Quisque ac imperdiet tortor, at lacinia ex. Duis vel ex hendrerit, commodo odio sed, aliquam enim. Ut arcu nulla, tincidunt eget arcu eget, molestie vulputate nisi. Nunc malesuada leo et est iaculis facilisis.',
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
icon: 'simple-icons:nextdotjs',
|
||||||
|
iconColor: '#000000',
|
||||||
|
name: 'Next.js',
|
||||||
|
url: 'https://nextjs.org/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'simple-icons:sass',
|
||||||
|
iconColor: '#CC6699',
|
||||||
|
name: 'SASS',
|
||||||
|
url: 'https://sass-lang.com/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'simple-icons:pnpm',
|
||||||
|
iconColor: '#F69220',
|
||||||
|
name: 'pnpm',
|
||||||
|
url: 'https://pnpm.io/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'simple-icons:eslint',
|
||||||
|
iconColor: '#4B32C3',
|
||||||
|
name: 'ESLint',
|
||||||
|
url: 'https://eslint.org/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'simple-icons:prettier',
|
||||||
|
iconColor: '#F7B93E',
|
||||||
|
name: 'Prettier',
|
||||||
|
url: 'https://prettier.io/',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
socials: [
|
||||||
|
{ name: 'Mockups', icon: 'fa6-solid:image', url: '#' },
|
||||||
|
{ name: 'App demo', icon: 'fa6-solid:desktop', url: '#' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const i18nData: I18n = {
|
||||||
|
locale: 'en-US',
|
||||||
|
translations: {
|
||||||
|
now: 'now',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="p-5">
|
||||||
|
<ProjectTimelineItem value={project} i18n={i18nData} />
|
||||||
|
</div>
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import type { ExperienceSection } from './experience-section';
|
import type { ExperienceSection } from './experience-section';
|
||||||
import type { FavoritesSection } from './favorites-section';
|
import type { FavoritesSection } from './favorites-section';
|
||||||
|
import type { I18n } from './i18n';
|
||||||
import type { MainSection } from './main-section';
|
import type { MainSection } from './main-section';
|
||||||
import type { PortfolioSection } from './portfolio-section';
|
import type { PortfolioSection } from './portfolio-section';
|
||||||
import type { Seo } from './seo';
|
import type { Seo } from './seo';
|
||||||
|
|
@ -7,6 +8,7 @@ import type { SkillsSection } from './skills-section';
|
||||||
import type { TestimonialsSection } from './testimonials-section';
|
import type { TestimonialsSection } from './testimonials-section';
|
||||||
|
|
||||||
export interface Data {
|
export interface Data {
|
||||||
|
i18n: I18n;
|
||||||
seo: Seo;
|
seo: Seo;
|
||||||
main: MainSection;
|
main: MainSection;
|
||||||
skills?: SkillsSection;
|
skills?: SkillsSection;
|
||||||
|
|
|
||||||
8
src/types/i18n.ts
Normal file
8
src/types/i18n.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import type { Locales } from 'locales-ts/types';
|
||||||
|
|
||||||
|
export interface I18n {
|
||||||
|
locale: Locales;
|
||||||
|
translations: {
|
||||||
|
now: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { Detail, LocalImage, SectionConfig, Social, Tag } from './common';
|
import type { Detail, LocalImage, SectionConfig, Social, Tag } from './common';
|
||||||
|
|
||||||
interface Project {
|
export interface Project {
|
||||||
name: string;
|
name: string;
|
||||||
image?: LocalImage;
|
image?: LocalImage;
|
||||||
startDate: Date;
|
startDate: Date;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue