Parcourir la source

Extract data

Use a temporary file for data source in the index layout.
master
TheoryOfNekomata il y a 1 mois
Parent
révision
7cb3253bed
9 fichiers modifiés avec 413 ajouts et 164 suppressions
  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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

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

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


+ 20
- 108
packages/web/src/pages/index.tsx Voir le fichier

@@ -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;

Chargement…
Annuler
Enregistrer