Browse Source

Extract data

Use a temporary file for data source in the index layout.
master
TheoryOfNekomata 6 months ago
parent
commit
7cb3253bed
9 changed files with 413 additions and 164 deletions
  1. +272
    -0
      packages/web/data.json
  2. +0
    -3
      packages/web/src/components/molecules/ContactCtaBanner/index.tsx
  3. +13
    -8
      packages/web/src/components/molecules/MakeSection/index.tsx
  4. +64
    -0
      packages/web/src/components/organisms/BlogLayout/index.tsx
  5. +29
    -30
      packages/web/src/components/organisms/IndexLayout/index.tsx
  6. +0
    -14
      packages/web/src/hooks/contact.ts
  7. +15
    -0
      packages/web/src/pages/blog/index.tsx
  8. +0
    -1
      packages/web/src/pages/contact/index.tsx
  9. +20
    -108
      packages/web/src/pages/index.tsx

+ 272
- 0
packages/web/data.json View File

@@ -0,0 +1,272 @@
{
"make": [
{
"id": 1,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 2,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 3,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 4,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 5,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 6,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 7,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 8,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 9,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 10,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 11,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 12,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 13,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 14,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 15,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 16,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 17,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 18,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 19,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 20,
"url": "http://www.example.com",
"date": "2023-07-03",
"type": "code",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
}
],
"envision": [
{
"id": 1,
"url": "http://www.example.com",
"imageUrl": "http://placehold.it/1",
"title": "Lorem ipsum dolor sit amet",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 2,
"url": "http://www.example.com",
"imageUrl": "http://placehold.it/1",
"title": "Lorem ipsum dolor sit amet",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 3,
"url": "http://www.example.com",
"imageUrl": "http://placehold.it/1",
"title": "Lorem ipsum dolor sit amet",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 4,
"url": "http://www.example.com",
"imageUrl": "http://placehold.it/1",
"title": "Lorem ipsum dolor sit amet",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 5,
"url": "http://www.example.com",
"imageUrl": "http://placehold.it/1",
"title": "Lorem ipsum dolor sit amet",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
},
{
"id": 6,
"url": "http://www.example.com",
"imageUrl": "http://placehold.it/1",
"title": "Lorem ipsum dolor sit amet",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum."
}
],
"featured": [
{
"title": "yasumi",
"description": "HATEOAS-first, resource-based backend framework in Node.",
"links": [
{
"href": "https://code.modal.sh/modal-soft/yasumi",
"children": "Explore Code",
"primary": true
}
],
"showcase": {
"type": "img",
"src": "/images/a96d02d8cc43cc3b9f1e77c43dfa5644.png"
}
},
{
"title": "formxtra",
"description": "Extract and set form values through the DOM—no frameworks required!",
"links": [
{
"href": "https://codepen.io/theoryofnekomata/pen/xxajmvJ",
"children": "View Demo"
},
{
"href": "https://code.modal.sh/TheoryOfNekomata/formxtra",
"children": "Explore Code",
"primary": true
}
],
"showcase": {
"type": "iframe",
"allowFullScreen": true,
"src": "https://codepen.io/theoryofnekomata/embed/xxajmvJ?default-tab=result&theme-id=dark",
"sandbox": "allow-forms allow-modals allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation-by-user-activation allow-downloads allow-presentation",
"allow": "accelerometer; camera; encrypted-media; display-capture; geolocation; gyroscope; microphone; midi; clipboard-read; clipboard-write; web-share"
}
},
{
"title": "tesseract",
"description": "Functional, accessible, aesthetic design system.",
"links": [
{
"href": "https://code.modal.sh/tesseract-design/tesseract",
"children": "Explore Code",
"primary": true
}
],
"showcase": {
"type": "img",
"src": "/images/162cab44da8420c50900d8f11c6da6fd.jpg"
}
},
{
"title": "numerica",
"description": "Gets the name of a number, even if it's stupidly big.",
"links": [
{
"href": "https://code.modal.sh/modal-soft/numerica",
"children": "Explore Code",
"primary": true
}
],
"showcase": {
"type": "img",
"src": "/images/d69ab7f4e5747b5b8f297e4ebe9770f5.png"
}
},
{
"title": "webvideo-transcript-summarizer",
"description": "Get transcript summaries of Web videos. Powered by OpenAI.",
"links": [
{
"href": "https://code.modal.sh/modal-soft/webvideo-transcript-summary",
"children": "Explore Code",
"primary": true
}
],
"showcase": {
"type": "img",
"src": "/images/3cd237361eada7fd30eb96d42d55ec00.jpg"
}
}
]
}

+ 0
- 3
packages/web/src/components/molecules/ContactCtaBanner/index.tsx View File

@@ -8,14 +8,12 @@ import * as WebActionReact from '@tesseract-design/web-action-react';
import {Brand} from '@/components/molecules/Brand';

export interface ContactCtaBannerProps {
onSubmit?: React.FormEventHandler<HTMLFormElement>;
visible?: boolean;
hasBrand?: boolean;
iceformProps?: Partial<ReturnType<typeof Iceform.useResponse>>;
}

export const ContactCtaBanner: React.FC<ContactCtaBannerProps> = ({
onSubmit,
visible: visibleProp = false,
hasBrand = false,
iceformProps = {},
@@ -83,7 +81,6 @@ export const ContactCtaBanner: React.FC<ContactCtaBannerProps> = ({
{...iceformProps}
className="mt-8"
aria-label="Contact Form"
onSubmit={onSubmit}
method="post"
action="/a/contact"
clientAction="/api/contact"


+ 13
- 8
packages/web/src/components/molecules/MakeSection/index.tsx View File

@@ -18,13 +18,18 @@ export const MakeSection: React.FC<MakeSectionProps> = ({
data,
}) => {
const groupedData = data.reduce(
(grouped, datum) => ({
...grouped,
[datum.date.getFullYear()]: [
...(grouped[datum.date.getFullYear()] ?? []),
datum,
],
}),
(grouped, datum) => {
const year = new Date(datum.date).getFullYear();
return {
...grouped,
[year]: [
...(
grouped[year] ?? []
),
datum,
],
};
},
{} as Record<string, MakeSectionDatum[]>,
);

@@ -86,7 +91,7 @@ export const MakeSection: React.FC<MakeSectionProps> = ({
key={id}
>
<a href="#" className="block">
<FeedItem {...datum} />
<FeedItem {...datum} date={new Date(datum.date)} />
</a>
</div>
))}


+ 64
- 0
packages/web/src/components/organisms/BlogLayout/index.tsx View File

@@ -0,0 +1,64 @@
import * as React from 'react';
import {Layouts, Widgets} from '@tesseract-design/viewfinder-react';
import Link from 'next/link';
import * as WebNavigationReact from '@tesseract-design/web-navigation-react';

export interface BlogLayoutProps {}

export const BlogLayout: React.FC<BlogLayoutProps> = () => (
<Layouts.LeftSidebar.Root
sidebarBaseWidget={
<Widgets.LeftSidebarBase>
<Layouts.LeftSidebar.SidebarContentContainer>
<aside className="my-16">
<h1 className="m-0">
Sidebar
</h1>
<div>
afasdfs
</div>
</aside>
</Layouts.LeftSidebar.SidebarContentContainer>
</Widgets.LeftSidebarBase>
}
>
<Layouts.LeftSidebar.MainContentContainer>
<main className="my-16 flex gap-8">
<article
className="rounded overflow-hidden relative flex flex-col gap-4 before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border-2 before:rounded-inherit px-4 py-3 before:pointer-events-none before:opacity-10"
>
<header>
<h1 className="m-0">
Article title
</h1>
<time className="font-headings lowercase font-extralight text-3xl">
2024 March 5 23:58
</time>
</header>
<div>
Excerpt lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod aliquam.
Lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod aliquam.
Lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod aliquam.
Lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod aliquam.
Lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod aliquam.
</div>
<footer className="flex justify-end">
<div className="w-48">
<WebNavigationReact.LinkButton
component={Link as unknown as 'a'}
href={{
pathname: '/feed',
} as unknown as string}
menuItem
block
subtext="Article Title"
>
Read more
</WebNavigationReact.LinkButton>
</div>
</footer>
</article>
</main>
</Layouts.LeftSidebar.MainContentContainer>
</Layouts.LeftSidebar.Root>
);

+ 29
- 30
packages/web/src/components/organisms/IndexLayout/index.tsx View File

@@ -14,7 +14,6 @@ export interface IndexLayoutProps {
makeSectionData?: MakeSectionProps['data'];
envisionSectionData?: EnvisionSectionProps['data'];
featuredProjectData?: FeaturedProjectSectionProps[];
onSubmit?: React.FormEventHandler<HTMLFormElement>;
contactVisible?: boolean;
hasMainLandingSection?: boolean;
contactHasBrand?: boolean;
@@ -26,7 +25,6 @@ export const IndexLayout: React.FC<IndexLayoutProps> = ({
makeSectionData,
envisionSectionData,
featuredProjectData = [],
onSubmit,
contactVisible = false,
hasMainLandingSection = false,
contactHasBrand = false,
@@ -40,36 +38,37 @@ export const IndexLayout: React.FC<IndexLayoutProps> = ({
<BackgroundGrid images={backgroundImages} />
</div>
</div>
{hasMainLandingSection && (
<>
<MainLandingSection
backgroundImages={backgroundImages}
<main className="contents">
{hasMainLandingSection && (
<>
<MainLandingSection
backgroundImages={backgroundImages}
/>
<div id="start" />
</>
)}
{Array.isArray(makeSectionData) && (
<MakeSection
data={makeSectionData}
/>
<div id="start" />
</>
)}
{Array.isArray(makeSectionData) && (
<MakeSection
data={makeSectionData}
/>
)}
{Array.isArray(envisionSectionData) && (
<EnvisionSection
data={envisionSectionData}
/>
)}
{featuredProjectData.map((featuredProjectProps) => (
<FeaturedProjectSection
key={featuredProjectProps.title}
{...featuredProjectProps}
)}
{Array.isArray(envisionSectionData) && (
<EnvisionSection
data={envisionSectionData}
/>
)}
{featuredProjectData.map((featuredProjectProps) => (
<FeaturedProjectSection
key={featuredProjectProps.title}
{...featuredProjectProps}
/>
))}
<ContactCtaBanner
visible={contactVisible}
hasBrand={contactHasBrand}
iceformProps={iceformProps}
/>
))}
<ContactCtaBanner
onSubmit={onSubmit}
visible={contactVisible}
hasBrand={contactHasBrand}
iceformProps={iceformProps}
/>
</main>
<Footer/>
</Layouts.Basic.Root>
);

+ 0
- 14
packages/web/src/hooks/contact.ts View File

@@ -1,14 +0,0 @@
import * as React from 'react';
import { getFormValues } from '@theoryofnekomata/formxtra';

export const useContactForm = () => {
const processContactForm: React.FormEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
const values = getFormValues(e.currentTarget);
console.log(values);
};

return React.useMemo(() => ({
processContactForm
}), []);
};

+ 15
- 0
packages/web/src/pages/blog/index.tsx View File

@@ -0,0 +1,15 @@
import {NextPage} from 'next';
import {useHuePulsate} from '@/hooks/effects';
import * as config from '@/config';
import {BlogLayout} from '@/components/organisms/BlogLayout';

const BlogPage: NextPage = () => {
useHuePulsate(config.effects.huePulsate);

return (
<BlogLayout
/>
);
};

export default BlogPage;

+ 0
- 1
packages/web/src/pages/contact/index.tsx View File

@@ -21,7 +21,6 @@ const IMAGE_CHOICES = [
];

const ContactPage: Iceform.NextPage = ({
req,
res,
}) => {
const {


+ 20
- 108
packages/web/src/pages/index.tsx View File

@@ -1,7 +1,5 @@
import type { NextPage } from 'next';
import * as React from 'react';
import {useHuePulsate} from '@/hooks/effects';
import {useContactForm} from '@/hooks/contact';
import {IndexLayout} from '@/components/organisms/IndexLayout';
import * as config from '@/config';
import * as Iceform from '@modal-sh/iceform-next';
@@ -22,110 +20,13 @@ const IMAGE_CHOICES = [
'/images/fe3050a31d3fb86accf26cc4bebec102.png',
];

const makeSectionData = new Array(20).fill(null).map((_, index) => ({
id: (index + 1).toString(),
url: 'http://www.example.com',
date: new Date('2023-07-03'),
type: 'code',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum.',
}));
export interface IndexPageProps {
data: any;
}

const envisionSectionData = new Array(6).fill(null).map((_, index) => ({
id: (index + 1).toString(),
url: 'http://www.example.com',
imageUrl: 'http://placehold.it/1',
title: 'Lorem ipsum dolor sit amet',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae diam eget nunc aliquam vestibulum. Sed vitae diam eget nunc aliquam vestibulum.',
}));

const featuredProjectData = [
{
title: 'yasumi',
description: 'HATEOAS-first, resource-based backend framework in Node.',
links:[
{
href: 'https://code.modal.sh/modal-soft/yasumi',
children: 'Explore Code',
primary: true,
},
],
showcase: {
type: 'img' as const,
src: '/images/a96d02d8cc43cc3b9f1e77c43dfa5644.png',
},
},
{
title: 'formxtra',
description: "Extract and set form values through the DOM—no frameworks required!",
links:[
{
href: 'https://codepen.io/theoryofnekomata/pen/xxajmvJ',
children: 'View Demo',
},
{
href: 'https://code.modal.sh/TheoryOfNekomata/formxtra',
children: 'Explore Code',
primary: true,
},
],
showcase: {
type: 'iframe' as const,
allowFullScreen: true,
src: 'https://codepen.io/theoryofnekomata/embed/xxajmvJ?default-tab=result&theme-id=dark',
sandbox: 'allow-forms allow-modals allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation-by-user-activation allow-downloads allow-presentation',
allow: 'accelerometer; camera; encrypted-media; display-capture; geolocation; gyroscope; microphone; midi; clipboard-read; clipboard-write; web-share',
},
},
{
title: 'tesseract',
description: 'Functional, accessible, aesthetic design system.',
links:[
{
href: 'https://code.modal.sh/tesseract-design/tesseract',
children: 'Explore Code',
primary: true,
},
],
showcase: {
type: 'img' as const,
src: '/images/162cab44da8420c50900d8f11c6da6fd.jpg',
},
},
{
title: 'numerica',
description: 'Gets the name of a number, even if it\'s stupidly big.',
links:[
{
href: 'https://code.modal.sh/modal-soft/numerica',
children: 'Explore Code',
primary: true,
},
],
showcase: {
type: 'img' as const,
src: '/images/d69ab7f4e5747b5b8f297e4ebe9770f5.png',
},
},
{
title: 'webvideo-transcript-summarizer',
description: 'Get transcript summaries of Web videos. Powered by OpenAI.',
links:[
{
href: 'https://code.modal.sh/modal-soft/webvideo-transcript-summary',
children: 'Explore Code',
primary: true,
},
],
showcase: {
type: 'img' as const,
src: '/images/3cd237361eada7fd30eb96d42d55ec00.jpg',
},
},
];

const IndexPage: Iceform.NextPage = ({
req,
const IndexPage: Iceform.NextPage<IndexPageProps> = ({
res,
data,
}) => {
const {
response,
@@ -139,15 +40,26 @@ const IndexPage: Iceform.NextPage = ({
return (
<IndexLayout
backgroundImages={IMAGE_CHOICES}
makeSectionData={makeSectionData}
envisionSectionData={envisionSectionData}
featuredProjectData={featuredProjectData}
makeSectionData={data.make}
envisionSectionData={data.envision}
featuredProjectData={data.featured}
hasMainLandingSection
iceformProps={iceformProps}
/>
);
};

export const getServerSideProps = Iceform.destination.getServerSideProps();
export const getServerSideProps = Iceform.destination.getServerSideProps({
fn: async (actionReq, actionRes, context) => {
const { readFile } = await import('fs/promises');
const dataJson = await readFile('data.json', 'utf-8');
const data = JSON.parse(dataJson);
return {
props: {
data,
},
};
},
});

export default IndexPage;

Loading…
Cancel
Save