Skip to content

Commit

Permalink
Merge branch 'master' into 7-extract-tag-cloud
Browse files Browse the repository at this point in the history
  • Loading branch information
tomek-i committed Aug 29, 2024
2 parents 55f1318 + a460ca1 commit 82ba81d
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 519 deletions.
5 changes: 2 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import { ErrorPage } from './pages/error';
import { HomePage } from './pages/home';

function App() {
const { posts, isLoading } = usePosts();

if (isLoading) return <></>;
const { posts } = usePosts();

return (
<>
Expand All @@ -28,6 +26,7 @@ function App() {
{posts.map((post) => (
<Route
key={post.frontmatter.company.name}
// TODO: we should create a util functio nthat slugifies the company name
path={post.frontmatter.company.name.toLowerCase()}
element={<PostComponent post={post} />}
/>
Expand Down
39 changes: 32 additions & 7 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useEffect, useRef } from 'react';
import { SocialNavigation } from '../SocialNavigation';

interface HeadingProps {}
Expand All @@ -9,14 +10,38 @@ const profile = {
};

export const Heading: React.FC<HeadingProps> = () => {
return (
<header className="mb-8 site-header">
<h1 className="site-title">{profile.name}</h1>
<p className="-mt-6 text-2xl">{profile.position}</p>
const socialNavRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const handleScroll = () => {
if (socialNavRef.current) {
if (window.scrollY > 100) {
// Adjust this value as needed
socialNavRef.current.classList.add('sticky');
} else {
socialNavRef.current.classList.remove('sticky');
}
}
};

<div className="flex justify-center mx-auto space-x-4 text-xs">
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);

return (
<>
<header className="mb-8 site-header">
<h1 className="site-title">{profile.name}</h1>
<p className="-mt-6 text-2xl">{profile.position}</p>
</header>
<nav
className="flex justify-center mx-auto space-x-4 text-xs"
ref={socialNavRef}
>
<SocialNavigation />
</div>
</header>
</nav>
</>
);
};
17 changes: 15 additions & 2 deletions src/components/Section/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,22 @@ import { SectionTitle } from './SectionTitle';

interface SectionProps extends React.PropsWithChildren {
className?: string;
isLoading?: boolean;
}
export function Section({ className, children }: SectionProps) {
return <section className={className}>{children}</section>;
export function Section({
className,
isLoading = false,
children,
}: SectionProps) {
const ToRender = isLoading ? (
<div className="w-full flex justify-center items-center">
<div className="w-8 h-8 border-4 border-blue-500 border-t-transparent border-solid rounded-full animate-spin"></div>
</div>
) : (
children
);

return <section className={className}>{ToRender}</section>;
}

Section.Wrapper = ({ children }: React.PropsWithChildren) => (
Expand Down
9 changes: 5 additions & 4 deletions src/components/SocialNavigation/SocialNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@ const socials = [

export const SocialNavigation: React.FC<SocialNavigationProps> = () => {
const { setShowContactFormModal } = useContactForm();
const size = 30;

const ICON_SIZE = 30;

return (
<div className="p-1 space-x-4 bg-white rounded-full">
<div className="p-1 space-x-4 bg-white rounded-full mb-4">
{socials.map((social) => (
<SocialIcon
url={social.url}
target="_blank"
rel="external nofollow noreferrer"
key={social.url}
style={{ height: size, width: size }}
style={{ height: ICON_SIZE, width: ICON_SIZE }}
className="transition-opacity duration-300 ease-in-out opacity-75 hover:opacity-100"
/>
))}
Expand All @@ -43,7 +44,7 @@ export const SocialNavigation: React.FC<SocialNavigationProps> = () => {
>
<SocialIcon
network="email"
style={{ height: size, width: size }}
style={{ height: ICON_SIZE, width: ICON_SIZE }}
className="transition-opacity duration-300 ease-in-out opacity-75 hover:opacity-100"
/>
</button>
Expand Down
2 changes: 2 additions & 0 deletions src/components/TimelineItem/TimelineItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export function TimelineItem({ timeline, isAlternate }: TimelineItemProps) {
<JobCard.Title />
<JobCard.Description />
{/* <JobCard.Responsibilities /> */}

{/* // TODO: as in the routing, this should use the slugify utility function */}
<Link
to={`career/${timeline.company.name}`}
className={
Expand Down
43 changes: 36 additions & 7 deletions src/components/hooks/usePosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,42 @@ type Module = {
default: string;
};

// Declare the __WebpackModuleApi namespace if it's not available
declare namespace __WebpackModuleApi {
interface RequireContext {
(id: string): any;
keys(): string[];
resolve(id: string): string;
id: string;
}
}
// Declare the NodeRequire interface with the context method
interface NodeRequire {
context: (
path: string,
deep?: boolean,
filter?: RegExp
) => __WebpackModuleApi.RequireContext;
}

export const usePosts = () => {
const [posts, setPosts] = useState<PostType<Frontmatter>[]>();
const [tags, setTags] = useState<TagCount[]>();
const [isLoading, setIsLoading] = useState(false);

const importAll = (r: any) => r.keys().map(r);

if (!process.env.REACT_APP_CONTENT_PATH)
throw new Error('REACT_APP_CONTENT_PATH not set');

type ImportAllFunction = (r: __WebpackModuleApi.RequireContext) => Module[];

const importAll: ImportAllFunction = (r) => r.keys().map(r);

const markdownFiles = importAll(
(require as any).context(process.env.REACT_APP_CONTENT_PATH, false, /\.md$/)
(require as unknown as NodeRequire).context(
process.env.REACT_APP_CONTENT_PATH,
false,
/\.md$/
)
);

const fetchMarkdownFile = async (
Expand Down Expand Up @@ -56,11 +80,16 @@ export const usePosts = () => {
const loadContent = async () => {
setIsLoading(true);

let results = await Promise.all<PostType<Frontmatter>[]>(
markdownFiles.map(fetchMarkdownFile)
);
// Create an array of promises
const promises = markdownFiles.map(fetchMarkdownFile);

// Wait for all promises to resolve
let results = await Promise.all(promises);

const unsortedTags = countTags(results);

setTags(unsortedTags?.sort((a, b) => b.count - a.count));

setTags(countTags(results));
results.sort((a, b) => {
return desc(
a.frontmatter.job.dates.start,
Expand Down
Loading

0 comments on commit 82ba81d

Please sign in to comment.