Преглед на файлове

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;

Зареждане…
Отказ
Запис