Skip to content

Commit fa5f490

Browse files
authored
fix: product page (#63)
* fix: product page * fix: upgrade nextjs * fix: support catrgory name for url slug * fix: upgrade node version
1 parent 20f122a commit fa5f490

26 files changed

+369
-348
lines changed

.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Test
22
on: [ pull_request ]
33

44
env:
5-
NODE_VERSION: "18.16.0"
5+
NODE_VERSION: "20.12.0"
66
PNPM_VERSION: "8.5.0"
77

88
concurrency:

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Use the official Node.js image as a base image
2-
FROM node:18
2+
FROM node:20
33

44
RUN apt-get update && apt-get install -y supervisor
55

app/layout.tsx

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
import './globals.scss';
2-
import type { Metadata } from 'next';
2+
import type { Metadata, Viewport } from 'next';
33
import Favicon from '../public/appflowy.svg';
44
import OpenGraph from '../public/images/og-image.png';
55
import App from '@/components/layout/app';
66
import { getGitData } from '@/lib/get-git';
77
import { getUAFromServer } from '@/lib/get-os';
88
import process from 'process';
99

10+
export const viewport: Viewport = {
11+
width: 'device-width',
12+
initialScale: 1,
13+
maximumScale: 1,
14+
userScalable: false,
15+
};
16+
1017
export const metadata: Metadata = {
1118
title: 'AppFlowy.IO',
1219
description: 'AppFlowy is an AI collaborative workspace where you achieve more without losing control of your data',
@@ -16,7 +23,6 @@ export const metadata: Metadata = {
1623
url: Favicon.src,
1724
},
1825
],
19-
viewport: 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no',
2026
openGraph:
2127
process.env.NODE_ENV === 'development'
2228
? undefined

app/templates/[category_id]/[id]/page.tsx renamed to app/templates/[category_name]/[id]/page.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import { CategoryIcon } from '@/components/template-center/icons';
1010
import RelatedTemplates from '@/components/template-center/template/related-templates';
1111
import Share from '@/components/template-center/template/share';
1212
import TemplateSection from '@/components/template-center/template/template-section';
13+
import { slugify } from '@/components/template-center/utils';
1314
import { getTemplateById } from '@/lib/templateAPI';
1415
import Link from 'next/link';
1516
import React from 'react';
1617
import '@/styles/template.scss';
1718
import { notFound } from 'next/navigation';
1819

19-
async function Page({ params }: { params: { id: string; category_id: string } }) {
20+
async function Page({ params }: { params: { id: string; category_name: string } }) {
2021
const id = params.id;
2122

2223
let data = null;
@@ -30,7 +31,7 @@ async function Page({ params }: { params: { id: string; category_id: string } })
3031

3132
return (
3233
<div className={'template-center'}>
33-
<TemplateSection template={data} categoryId={params.category_id} />
34+
<TemplateSection template={data} categoryName={params.category_name} />
3435
<div
3536
className={
3637
'flex w-full flex-col items-center gap-[70px] bg-white px-[170px] py-[110px] max-lg:gap-[10vh] max-lg:px-[8vw] max-lg:py-[10vh]'
@@ -46,7 +47,7 @@ async function Page({ params }: { params: { id: string; category_id: string } })
4647
<div className={'title'}>Category</div>
4748
{data.categories.map((category) => (
4849
<Link
49-
href={`/templates/${category.id}`}
50+
href={`/templates/${slugify(category.name)}`}
5051
style={{
5152
backgroundColor: category.bg_color,
5253
}}

app/templates/[category_id]/page.tsx renamed to app/templates/[category_name]/page.tsx

+21-12
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,35 @@ import CategoryTemplatesHeader from '@/components/template-center/category-templ
22
import Sidebar from '@/components/template-center/sidebar';
33
import TemplateList from '@/components/template-center/template-list';
44
import { TemplatesProvider } from '@/components/template-center/templates-context';
5+
import { slugify } from '@/components/template-center/utils';
56
import { getCategories, getCategoryTemplateList } from '@/lib/templateAPI';
67
import { notFound } from 'next/navigation';
78
import React from 'react';
89
import Community from '@/components/template-center/community';
910

1011
import '@/styles/template.scss';
1112

12-
async function Page({ params }: { params: { category_id: string } }) {
13-
const id = params.category_id;
13+
async function Page({ params }: { params: { category_name: string } }) {
14+
const name = params.category_name;
1415

1516
let data = null;
1617

1718
try {
18-
data = await getData(id);
19+
data = await getData(name);
1920
} catch (error) {
2021
console.error(error);
2122
notFound();
2223
}
2324

24-
const categories = await getCategories();
25-
const category = categories.find((item) => item.id === id);
26-
2725
return (
2826
<div className={'template-center'}>
2927
<div className={'main'}>
30-
<TemplatesProvider selectedCategoryId={id} categoryTemplates={data} categories={categories}>
31-
<CategoryTemplatesHeader category={category} />
28+
<TemplatesProvider
29+
selectedCategoryId={data.category.id}
30+
categoryTemplates={data.data}
31+
categories={data.categories}
32+
>
33+
<CategoryTemplatesHeader category={data.category} />
3234
<div className={'content'}>
3335
<Sidebar />
3436
<TemplateList />
@@ -44,12 +46,19 @@ export const revalidate = 10;
4446

4547
export default Page;
4648

47-
async function getData(id: string) {
48-
const data = await getCategoryTemplateList(id);
49+
async function getData(name: string) {
50+
const categories = await getCategories();
51+
const category = categories.find((item) => slugify(item.name) === name);
52+
53+
if (!category) {
54+
throw new Error(`Failed to fetch category ${name}`);
55+
}
56+
57+
const data = await getCategoryTemplateList(category.id);
4958

5059
if (!data) {
51-
throw new Error(`Failed to fetch category data ${id}`);
60+
throw new Error(`Failed to fetch category data ${category.id}`);
5261
}
5362

54-
return data;
63+
return { data, category, categories };
5564
}

components/product/ai-examples.tsx

+11-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import MuiTab from '@mui/material/Tab';
1111
import MuiTabs from '@mui/material/Tabs';
1212
import { useInView } from 'framer-motion';
1313
import Image from 'next/image';
14-
import React, { useMemo } from 'react';
14+
import React, { useEffect, useMemo } from 'react';
1515

1616
function AiExamples() {
1717
const [value, setValue] = React.useState('write');
@@ -30,18 +30,25 @@ function AiExamples() {
3030
const ref = React.useRef<HTMLDivElement>(null);
3131
const inView = useInView(ref);
3232

33-
useAutoPlay({
33+
const { start, stop } = useAutoPlay({
3434
options: tabOptions,
3535
onChange: setValue,
36-
play: inView,
37-
defaultOption: 'write',
3836
});
3937

38+
useEffect(() => {
39+
if (!inView) {
40+
stop();
41+
} else {
42+
start();
43+
}
44+
}, [inView, start, stop]);
45+
4046
return (
4147
<div ref={ref} className={'ai-examples'}>
4248
<MuiTabs value={value} onChange={handleChange}>
4349
{tabOptions.map((tab) => (
4450
<MuiTab
51+
onClick={() => start()}
4552
className={`ai-example-tab ${value === tab.value ? 'selected' : ''}`}
4653
key={tab.value}
4754
value={tab.value}

components/product/ai-icon.tsx

-42
This file was deleted.

components/product/automate-icon.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React from 'react';
33
function AutomateIcon() {
44
return (
55
<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' fill='none'>
6-
<g opacity='0.6'>
6+
<g opacity='1'>
77
<path
88
d='M10.3117 5.95425C7.90846 5.95425 5.95347 7.90924 5.95347 10.3125C5.95347 12.7158 7.90846 14.6707 10.3117 14.6707C12.715 14.6707 14.67 12.7158 14.67 10.3125C14.67 7.90924 12.715 5.95425 10.3117 5.95425ZM10.3117 13.4255C8.59488 13.4255 7.19869 12.0293 7.19869 10.3125C7.19869 8.59566 8.59488 7.19947 10.3117 7.19947C12.0286 7.19947 13.4248 8.59566 13.4248 10.3125C13.4248 12.0293 12.0286 13.4255 10.3117 13.4255Z'
99
fill='currentColor'

components/product/calendar-icon.tsx

-36
This file was deleted.

components/product/icons.tsx

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React from 'react';
2+
3+
export function TemplateIcon() {
4+
return (
5+
<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' fill='none'>
6+
<g opacity='1'>
7+
<path
8+
d='M10.4469 2.8263L10.3987 2.81336L10.3857 2.86166L8.66025 9.30116L8.64731 9.34946L8.69561 9.3624L10.2392 9.776L10.2763 9.78593L10.2954 9.75271L11.1005 8.35836C11.7227 7.28058 13.2784 7.28058 13.9006 8.35836L15.2183 10.6407L15.2787 10.7452L15.3099 10.6286L16.9218 4.613L16.9348 4.5647L16.8865 4.55176L10.4469 2.8263ZM16.203 12.2648L16.1716 12.2918L16.1923 12.3277L18.2307 15.8584C18.853 16.9361 18.0752 18.2834 16.8307 18.2834H8.17041C7.22595 18.2834 6.54962 17.5072 6.55126 16.6611L6.55136 16.6087L6.49899 16.611C6.41664 16.6148 6.33381 16.6167 6.25053 16.6167C3.2866 16.6167 0.883862 14.214 0.883862 11.25C0.883862 8.2861 3.2866 5.88336 6.25053 5.88336C6.80273 5.88336 7.33536 5.96674 7.83657 6.12157L7.88618 6.1369L7.89962 6.08674L8.87243 2.45618C9.10352 1.59374 9.99 1.08193 10.8524 1.31302L17.2919 3.03848C18.1544 3.26957 18.6662 4.15605 18.4351 5.01848L16.7096 11.458C16.6222 11.7842 16.4411 12.0602 16.203 12.2648ZM9.43271 11.247L9.46529 11.1906L9.40235 11.1737L8.29013 10.8757C7.42769 10.6446 6.91588 9.75812 7.14697 8.89568L7.46769 7.69872L7.47994 7.65301L7.43497 7.63827C7.06218 7.51609 6.66402 7.45003 6.25053 7.45003C4.15185 7.45003 2.45053 9.15135 2.45053 11.25C2.45053 13.3487 4.15185 15.05 6.25053 15.05C6.61697 15.05 6.97138 14.9981 7.30677 14.9013L7.32613 14.8957L7.3362 14.8783L9.43271 11.247ZM16.9173 16.7167L16.874 16.6417L12.5438 9.14169L12.5005 9.06669L12.4572 9.14169L8.12711 16.6417L8.08381 16.7167H8.17041H16.8307H16.9173Z'
9+
fill='currentColor'
10+
stroke='currentColor'
11+
strokeWidth='0.1'
12+
/>
13+
</g>
14+
</svg>
15+
);
16+
}
17+
18+
export function KanbanIcon() {
19+
return (
20+
<svg width='21' height='20' viewBox='0 0 21 20' fill='none' xmlns='http://www.w3.org/2000/svg'>
21+
<g opacity='1'>
22+
<path
23+
fillRule='evenodd'
24+
clipRule='evenodd'
25+
d='M8.625 2.5C9.31536 2.5 9.875 3.05964 9.875 3.75V16.25C9.875 16.9404 9.31536 17.5 8.625 17.5H5.5C4.80964 17.5 4.25 16.9404 4.25 16.25V3.75C4.25 3.05964 4.80964 2.5 5.5 2.5H8.625ZM8.625 16.25V3.75H5.5V16.25H8.625Z'
26+
fill='currentColor'
27+
/>
28+
<path
29+
fillRule='evenodd'
30+
clipRule='evenodd'
31+
d='M15.5 2.5C16.1904 2.5 16.75 3.05964 16.75 3.75V16.25C16.75 16.9404 16.1904 17.5 15.5 17.5H12.375C11.6846 17.5 11.125 16.9404 11.125 16.25V3.75C11.125 3.05964 11.6846 2.5 12.375 2.5H15.5ZM15.5 16.25V3.75H12.375V16.25H15.5Z'
32+
fill='currentColor'
33+
/>
34+
</g>
35+
</svg>
36+
);
37+
}
38+
39+
export function ProjectsIcon() {
40+
return (
41+
<svg xmlns='http://www.w3.org/2000/svg' width='21' height='21' viewBox='0 0 21 21' fill='none'>
42+
<g opacity='1'>
43+
<path
44+
fillRule='evenodd'
45+
clipRule='evenodd'
46+
d='M8.38714 3.42857H16.3929C17.3199 3.42857 18.0714 4.18009 18.0714 5.10714V6.99608H8.38714V3.42857ZM8.38714 8.42465H18.0714V12.5742H8.38714V8.42465ZM6.95857 12.5742V8.42465H2.92857V12.5742H6.95857ZM2.92857 14.0028H6.95857V17.5714H4.60714C3.68009 17.5714 2.92857 16.8199 2.92857 15.8929V14.0028ZM8.38714 14.0028H18.0714V15.8929C18.0714 16.8199 17.3199 17.5714 16.3929 17.5714H8.38714V14.0028ZM6.95857 3.42857V6.99608H2.92857V5.10714C2.92857 4.18009 3.68009 3.42857 4.60714 3.42857H6.95857ZM1.5 5.10714C1.5 3.39112 2.89112 2 4.60714 2H16.3929C18.1089 2 19.5 3.39112 19.5 5.10714V15.8929C19.5 17.6089 18.1089 19 16.3929 19H4.60714C2.89112 19 1.5 17.6089 1.5 15.8929V5.10714Z'
47+
fill='currentColor'
48+
/>
49+
</g>
50+
</svg>
51+
);
52+
}
53+
54+
export function AiIcon() {
55+
return (
56+
<svg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'>
57+
<g opacity='1'>
58+
<path
59+
fillRule='evenodd'
60+
clipRule='evenodd'
61+
d='M8.03559 3.91001C8.24508 3.76431 8.49414 3.68622 8.74931 3.68622C9.00448 3.68622 9.25353 3.76431 9.46302 3.91001C9.67251 4.0557 9.83239 4.26202 9.92118 4.50124L9.92169 4.50261L11.4217 8.57292L11.4235 8.57578L11.4263 8.57758L15.498 10.0781C15.7373 10.1669 15.9436 10.3268 16.0893 10.5363C16.235 10.7458 16.3131 10.9948 16.3131 11.25C16.3131 11.5051 16.235 11.7542 16.0893 11.9637C15.9436 12.1732 15.7373 12.3331 15.498 12.4219L15.4967 12.4224L11.4264 13.9224L11.4235 13.9242L11.4217 13.927L9.92169 17.9973L9.92118 17.9987C9.83239 18.2379 9.6725 18.4443 9.46302 18.59C9.25353 18.7356 9.00448 18.8137 8.74931 18.8137C8.49414 18.8137 8.24508 18.7356 8.03559 18.59C7.82611 18.4443 7.66623 18.2379 7.57743 17.9987L7.57692 17.9973L6.07692 13.927L6.07511 13.9242L6.07383 13.9231L6.07228 13.9224L2.00194 12.4224L2.00057 12.4219C1.76134 12.3331 1.55503 12.1732 1.40933 11.9637C1.26364 11.7542 1.18555 11.5051 1.18555 11.25C1.18555 10.9948 1.26364 10.7458 1.40933 10.5363C1.55503 10.3268 1.76134 10.1669 2.00057 10.0781L2.00194 10.0776L6.07225 8.5776L6.07511 8.57578L6.07691 8.57295L7.57692 4.50261L7.57743 4.50124C7.66623 4.26202 7.82611 4.0557 8.03559 3.91001ZM10.2488 13.4948C10.3117 13.324 10.4109 13.169 10.5396 13.0403C10.6683 12.9116 10.8234 12.8124 10.9941 12.7495L15.0631 11.25L10.9942 9.7505C10.8234 9.68758 10.6683 9.58834 10.5396 9.45966C10.4109 9.33098 10.3117 9.17592 10.2488 9.00516L8.74931 4.93622L7.24983 9.00513C7.1869 9.17588 7.08767 9.33098 6.95899 9.45966C6.83031 9.58834 6.67524 9.68756 6.50449 9.75049L2.43555 11.25L6.50446 12.7495C6.67521 12.8124 6.83031 12.9116 6.95899 13.0403C7.08767 13.169 7.18689 13.324 7.24981 13.4948L8.74931 17.5637L10.2488 13.4948Z'
62+
fill='currentColor'
63+
/>
64+
<path
65+
fillRule='evenodd'
66+
clipRule='evenodd'
67+
d='M13.7493 0.625C14.0945 0.625 14.3743 0.904822 14.3743 1.25V5C14.3743 5.34518 14.0945 5.625 13.7493 5.625C13.4042 5.625 13.1243 5.34518 13.1243 5V1.25C13.1243 0.904822 13.4042 0.625 13.7493 0.625Z'
68+
fill='currentColor'
69+
/>
70+
<path
71+
fillRule='evenodd'
72+
clipRule='evenodd'
73+
d='M11.2493 3.125C11.2493 2.77982 11.5292 2.5 11.8743 2.5H15.6243C15.9695 2.5 16.2493 2.77982 16.2493 3.125C16.2493 3.47018 15.9695 3.75 15.6243 3.75H11.8743C11.5292 3.75 11.2493 3.47018 11.2493 3.125Z'
74+
fill='currentColor'
75+
/>
76+
<path
77+
fillRule='evenodd'
78+
clipRule='evenodd'
79+
d='M17.4993 5C17.8445 5 18.1243 5.27982 18.1243 5.625V8.125C18.1243 8.47018 17.8445 8.75 17.4993 8.75C17.1542 8.75 16.8743 8.47018 16.8743 8.125V5.625C16.8743 5.27982 17.1542 5 17.4993 5Z'
80+
fill='currentColor'
81+
/>
82+
<path
83+
fillRule='evenodd'
84+
clipRule='evenodd'
85+
d='M15.6243 6.875C15.6243 6.52982 15.9042 6.25 16.2493 6.25H18.7493C19.0945 6.25 19.3743 6.52982 19.3743 6.875C19.3743 7.22018 19.0945 7.5 18.7493 7.5H16.2493C15.9042 7.5 15.6243 7.22018 15.6243 6.875Z'
86+
fill='currentColor'
87+
/>
88+
</g>
89+
</svg>
90+
);
91+
}

components/product/kanban-icon.tsx

-24
This file was deleted.

0 commit comments

Comments
 (0)