Skip to content

Commit

Permalink
#10: Create Project Grid Page
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul-Hume committed Feb 15, 2023
1 parent 8a1535a commit 2dc74ac
Show file tree
Hide file tree
Showing 16 changed files with 171 additions and 8 deletions.
16 changes: 16 additions & 0 deletions src/Components/Card/Card.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.action-area {
height: 100% !important;
display: flex !important;
justify-content: flex-start !important;
align-items: flex-start !important;
flex-direction: column !important;
}

.image {
height: 100px;
width: 100%;
}

.description {
margin-bottom: 1rem !important;
}
35 changes: 35 additions & 0 deletions src/Components/Card/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Card as MuiCard, CardActionArea, CardContent, CardMedia, Typography } from '@mui/material';
import Contentful from 'contentful';

import { TagBlock } from 'Components/TagBlock';

import styles from './Card.module.css';

interface CardProps {
image?: Contentful.Asset;
title: Contentful.EntryFields.Text;
description?: Contentful.EntryFields.Text;
tags?: Contentful.TagLink[];
onClick: () => void;
}

export const Card = ({ onClick, image, title, description, tags }: CardProps) => {
return (
<MuiCard className={styles.container}>
<CardActionArea className={styles['action-area']} onClick={onClick}>
{image && <CardMedia className={styles.image} image={image.fields.file.url} title="foofoo" />}
<CardContent className={styles.content}>
<Typography className={styles.title} gutterBottom variant="h5" component="div">
{title}
</Typography>
{description && (
<Typography className={styles.description} variant="body2" color="text.secondary">
{description}
</Typography>
)}
{tags && <TagBlock tags={tags} />}
</CardContent>
</CardActionArea>
</MuiCard>
);
};
1 change: 1 addition & 0 deletions src/Components/Card/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Card';
1 change: 1 addition & 0 deletions src/Components/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './AvailableFrom';
export * from './Card';
export * from './CvDownloadButton';
export * from './ErrorAlert';
export * from './Grid';
Expand Down
1 change: 1 addition & 0 deletions src/Hooks/Api/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './useExperienceApi';
export * from './useJournalApi';
export * from './usePageContentApi';
export * from './useProjectsApi';
export * from './useSkillsApi';
17 changes: 17 additions & 0 deletions src/Hooks/Api/useProjectsApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useQuery } from '@tanstack/react-query';

import { useContentfulClient } from '../useContentfulClient';

import { ProjectItem } from 'Types';

export const useProjectsApi = () => {
const { fetchEntries } = useContentfulClient();

return useQuery({
queryKey: ['useProjectsApi'],
queryFn: () => fetchEntries<ProjectItem>('project', {
order: '-sys.createdAt',
}),
staleTime: Infinity,
});
};
5 changes: 2 additions & 3 deletions src/Modules/NavBar/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react';
import { Description,DeveloperMode,FilterAlt, Home } from '@mui/icons-material';
import { Description,DeveloperMode,FilterAlt, Home, SettingsEthernet } from '@mui/icons-material';
import { Avatar, IconButton } from '@mui/material';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
Expand Down Expand Up @@ -49,8 +49,7 @@ export const NavBar = ({ location = 'header' }: NavBarProps) => {
<NavLink to="/" icon={<Home />}>Home</NavLink>
<NavLink to="/experience" icon={<DeveloperMode />}>Experience</NavLink>
<NavLink to="/journal" icon={<Description />}>Journal</NavLink>
{/* <NavLink to="/projects">Projects</NavLink>
<NavLink to="/history">History</NavLink> */}
<NavLink to="/projects" icon={<SettingsEthernet />}>Projects</NavLink>
</>
)}

Expand Down
43 changes: 43 additions & 0 deletions src/Modules/ProjectsGrid/ProjectsGrid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useNavigate } from 'react-router-dom';

import { Card, ErrorAlert, Grid, LoadingSpinner, NoDataAlert } from 'Components';

import { useProjectsApi } from 'Hooks';

export const ProjectsGrid = () => {
const { data, isLoading, error } = useProjectsApi();
const navigate = useNavigate();

const navigateProjectItem = (slug: string) => {
navigate(`/projects/${slug}`);
};

if (isLoading) {
return <LoadingSpinner />;
}

if (error) {
return <ErrorAlert error="Error retrieving projects list" />;
}

if (!isLoading && !error && !data?.items?.length) {
return <NoDataAlert />;
}

console.log(data);

return (
<Grid>
{data?.items?.map(project => (
<Card
key={project.sys.id}
image={project?.fields?.heroImage}
title={project.fields.title}
description={project.fields.shortDescription}
tags={project.metadata.tags}
onClick={() => navigateProjectItem(project.fields.slug)}
/>
))}
</Grid>
);
};
1 change: 1 addition & 0 deletions src/Modules/ProjectsGrid/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ProjectsGrid';
1 change: 1 addition & 0 deletions src/Modules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './Header';
export * from './JournalGrid';
export * from './NavBar';
export * from './PageContent';
export * from './ProjectsGrid';
export * from './SideBar';
export * from './SocialLinks';
export * from './TagDrawer';
7 changes: 7 additions & 0 deletions src/Routes/Projects/ProjectsItemPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const ProjectsItemPage = () => {
return (
<section>
projects item here
</section>
);
};
34 changes: 34 additions & 0 deletions src/Routes/Projects/ProjectsPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useEffect } from 'react';
import { Helmet } from 'react-helmet-async';
import { useLocation,useOutlet } from 'react-router-dom';

import { Title } from 'Components';
import { ProjectsGrid } from 'Modules';

import { useUi } from 'Context/uiContext';
import { useAnalytics } from 'Hooks/useAnalytics/useAnalytics';

export const ProjectsPage = () => {
const outlet = useOutlet();
const { pageTitle } = useUi();
const { pageView } = useAnalytics();
const { pathname } = useLocation();

useEffect(() => {
if (!outlet) {
pageView(pathname);
}
});

return (
<>
<Helmet>
<title>Projects {pageTitle}</title>
</Helmet>

<Title title="Projects" />

<ProjectsGrid />
</>
);
};
2 changes: 2 additions & 0 deletions src/Routes/Projects/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './ProjectsItemPage';
export * from './ProjectsPage';
3 changes: 2 additions & 1 deletion src/Routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from './Error';
export * from './Experience';
export * from './Home';
export * from './Journal';
export * from './Root';
export * from './Projects';
export * from './Root';
7 changes: 4 additions & 3 deletions src/Types/project.types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import Contentful from 'contentful';

export interface ProjectItem {
title: Contentful.EntryFields.Text;
slug: Contentful.EntryFields.Text;
heroImage: Contentful.Asset;
title: Contentful.EntryFields.Text;
shortDescription: Contentful.EntryFields.Text;
description: Contentful.EntryFields.RichText;
url: Contentful.EntryFields.Text;
repo: Contentful.EntryFields.Text;
description: Contentful.EntryFields.RichText;
image: Contentful.Asset;
}
5 changes: 4 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom/client';
import { createBrowserRouter ,RouterProvider } from 'react-router-dom';

import { ErrorPage, ExperiencePage, JournalItemPage, JournalPage, Root } from 'Routes';
import { ErrorPage, ExperiencePage, JournalItemPage, JournalPage, ProjectsItemPage, ProjectsPage, Root } from 'Routes';

import './index.css';
import './Themes/dracular-prism.css';
Expand All @@ -16,6 +16,9 @@ const router = createBrowserRouter([
{ path: 'journal', element: <JournalPage />, children: [
{ path: ':slug', element: <JournalItemPage /> }
] },
{ path: 'projects', element: <ProjectsPage />, children: [
{ path: ':slug', element: <ProjectsItemPage /> }
] },
] },
]);

Expand Down

0 comments on commit 2dc74ac

Please sign in to comment.