瀏覽代碼

Extract data

Use a temporary file for data source in the index layout.
master
TheoryOfNekomata 1 月之前
父節點
當前提交
7cb3253bed
共有 9 個文件被更改,包括 413 次插入164 次删除
  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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

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

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


+ 20
- 108
packages/web/src/pages/index.tsx 查看文件

@@ -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…
取消
儲存