Skip to content

Commit

Permalink
feat(cow-fi): upgrade project structure to /app (#5167)
Browse files Browse the repository at this point in the history
  • Loading branch information
shoom3301 authored Dec 11, 2024
1 parent a38a3e5 commit ed152f7
Show file tree
Hide file tree
Showing 130 changed files with 7,315 additions and 7,495 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,4 @@ out

# Next.js sitemap
apps/cow-fi/public/robots.txt
apps/cow-fi/public/sitemap*
apps/cow-fi/public/sitemap*
2 changes: 1 addition & 1 deletion apps/cow-fi/.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ DUNE_API_KEY=tuBkOcda6ymMvmnpIX9Qer9Xb5hJ2rf8
NEXT_PUBLIC_GOOGLE_ANALYTICS=
NEXT_PUBLIC_AWS_API_ENDPOINT="https://bff.cow.fi/proxies/tokens"
NEXT_PUBLIC_LAUNCH_DARKLY_KEY=
NEXT_PUBLIC_SITE_URL="https://cow.fi"
NEXT_PUBLIC_SITE_URL="https://cow.fi"
5 changes: 5 additions & 0 deletions apps/cow-fi/app/(learn)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Layout } from '@/components/Layout'

export default function LayoutPage({ children }: { children: React.ReactNode }) {
return <Layout>{children}</Layout>
}
101 changes: 101 additions & 0 deletions apps/cow-fi/app/(learn)/learn/[article]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
'use server'

import React from 'react'
import {
Article,
getAllArticleSlugs,
getArticleBySlug,
getArticles,
getCategories,
SharedRichTextComponent,
} from '../../../../services/cms'
import { ArticlePageComponent } from '@/components/ArticlePageComponent'
import { notFound } from 'next/navigation'
import type { Metadata } from 'next'
import { stripHtmlTags } from '@/util/stripHTMLTags'
import { getPageMetadata } from '@/util/getPageMetadata'

function isRichTextComponent(block: any): block is SharedRichTextComponent {
return block.body !== undefined
}

type Props = {
params: Promise<{ article: string }>
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
const articleSlug = (await params).article

if (!articleSlug) return {}

const article = await getArticleBySlug(articleSlug)
const attributes = article?.attributes
const { title, blocks, description, cover } = attributes || {}
const coverImageUrl = cover?.data?.attributes?.url

const content =
blocks?.map((block: SharedRichTextComponent) => (isRichTextComponent(block) ? block.body : '')).join(' ') || ''
const plainContent = stripHtmlTags(content)

return getPageMetadata({
absoluteTitle: `${title} - CoW DAO`,
description: description
? stripHtmlTags(description)
: plainContent.length > 150
? stripHtmlTags(plainContent.substring(0, 147)) + '...'
: stripHtmlTags(plainContent),
image: coverImageUrl,
})
}

export async function generateStaticParams() {
const slugs = await getAllArticleSlugs()

return slugs.map((article) => ({ article }))
}

export default async function ArticlePage({ params }: Props) {
const articleSlug = (await params).article
const article = await getArticleBySlug(articleSlug)

if (!article) {
return notFound()
}

const articlesResponse = await getArticles()
const articles = articlesResponse.data

// Fetch featured articles
const featuredArticlesResponse = await getArticles({
filters: {
featured: {
$eq: true,
},
},
pageSize: 7, // Limit to 7 articles
})
const featuredArticles = featuredArticlesResponse.data

const randomArticles = getRandomArticles(articles, 3)
const categoriesResponse = await getCategories()
const allCategories =
categoriesResponse?.map((category: any) => ({
name: category?.attributes?.name || '',
slug: category?.attributes?.slug || '',
})) || []

return (
<ArticlePageComponent
article={article}
articles={articles}
randomArticles={randomArticles}
featuredArticles={featuredArticles}
allCategories={allCategories}
/>
)
}

function getRandomArticles(articles: Article[], count: number): Article[] {
const shuffled = articles.sort(() => 0.5 - Math.random())
return shuffled.slice(0, count)
}
10 changes: 10 additions & 0 deletions apps/cow-fi/app/(learn)/learn/articles/[[...pageIndex]]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Metadata } from 'next'

export const metadata: Metadata = {
title: 'All articles',
description: 'All knowledge base articles in the Cow DAO ecosystem',
}

export default function LayoutPage({ children }: { children: React.ReactNode }) {
return children
}
67 changes: 67 additions & 0 deletions apps/cow-fi/app/(learn)/learn/articles/[[...pageIndex]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use server'

import { Article, getArticles, getCategories } from '../../../../../services/cms'
import { ArticlesPageComponents } from '@/components/ArticlesPageComponents'

const ITEMS_PER_PAGE = 24

type Props = {
params: Promise<{ pageIndex?: string }>
}

export type ArticlesResponse = {
data?: Article[]
meta?: {
pagination?: {
total?: number
}
}
}

export async function generateStaticParams() {
const articlesResponse = await getArticles({ page: 0, pageSize: ITEMS_PER_PAGE })
const totalArticles = articlesResponse.meta?.pagination?.total || 0
const totalPages = Math.ceil(totalArticles / ITEMS_PER_PAGE)

return Array.from({ length: totalPages }, (_, i) => ({ pageIndex: [(i + 1).toString()] }))
}

export default async function Page({ params }: Props) {
const pageParam = (await params)?.pageIndex
const page = pageParam && pageParam.length > 0 ? parseInt(pageParam[0], 10) : 1

const articlesResponse = (await getArticles({ page, pageSize: ITEMS_PER_PAGE })) as ArticlesResponse

const totalArticles = articlesResponse.meta?.pagination?.total || 0
const articles =
articlesResponse.data?.map((article: Article) => ({
...article,
id: article.id || 0,
attributes: {
...article.attributes,
title: article.attributes?.title ?? 'Untitled',
description: article.attributes?.description ?? '',
slug: article.attributes?.slug ?? 'no-slug',
featured: article.attributes?.featured ?? false,
publishDateVisible: article.attributes?.publishDateVisible ?? false,
cover: article.attributes?.cover ?? {},
blocks: article.attributes?.blocks ?? [],
},
})) || []

const categoriesResponse = await getCategories()
const allCategories =
categoriesResponse?.map((category: any) => ({
name: category?.attributes?.name || '',
slug: category?.attributes?.slug || '',
})) || []

return (
<ArticlesPageComponents
articles={articles}
totalArticles={totalArticles}
currentPage={page}
allCategories={allCategories}
/>
)
}
12 changes: 12 additions & 0 deletions apps/cow-fi/app/(learn)/learn/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Metadata } from 'next'

export const metadata: Metadata = {
title: {
default: 'Knowledge Base - CoW DAO',
template: '%s - CoW DAO',
},
}

export default function LayoutPage({ children }: { children: React.ReactNode }) {
return children
}
45 changes: 45 additions & 0 deletions apps/cow-fi/app/(learn)/learn/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use server'

import { getArticles, getCategories } from '../../../services/cms'

import { LearnPageComponent } from '@/components/LearnPageComponent'

export default async function Page() {
const categoriesResponse = await getCategories()
const articlesResponse = await getArticles()

const featuredArticlesResponse = await getArticles({
filters: { featured: { $eq: true } },
pageSize: 6,
})

const categories =
categoriesResponse?.map((category: any) => {
const imageUrl = category?.attributes?.image?.data?.attributes?.url || ''

return {
name: category?.attributes?.name || '',
slug: category?.attributes?.slug || '',
description: category?.attributes?.description || '',
bgColor: category?.attributes?.backgroundColor || '#fff',
textColor: category?.attributes?.textColor || '#000',
link: `/learn/topic/${category?.attributes?.slug}`,
iconColor: '#fff',
imageUrl,
}
}) || []

const featuredArticles = featuredArticlesResponse.data.map((article) => {
const attributes = article.attributes
return {
title: attributes?.title || 'No title',
description: attributes?.description || 'No description',
link: `/learn/${attributes?.slug || 'no-slug'}`,
cover: attributes?.cover?.data?.attributes?.url || '',
}
})

return (
<LearnPageComponent categories={categories} articles={articlesResponse.data} featuredArticles={featuredArticles} />
)
}
64 changes: 64 additions & 0 deletions apps/cow-fi/app/(learn)/learn/topic/[topicSlug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use server'

import React from 'react'
import { getAllCategorySlugs, getArticles, getCategories, getCategoryBySlug } from '../../../../../services/cms'
import { TopicPageComponent } from '@/components/TopicPageComponent'
import { notFound } from 'next/navigation'
import type { Metadata } from 'next'

type Props = {
params: Promise<{ topicSlug: string }>
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
const topicSlug = (await params).topicSlug

if (!topicSlug) return {}

const category = await getCategoryBySlug(topicSlug)
const { name, description } = category?.attributes || {}

return {
title: name,
description,
}
}

export async function generateStaticParams() {
const categoriesResponse = await getAllCategorySlugs()

return categoriesResponse.map((topicSlug) => ({ topicSlug }))
}

export default async function TopicPage({ params }: Props) {
const slug = (await params).topicSlug

const category = await getCategoryBySlug(slug)

if (!category) {
return notFound()
}

const articlesResponse = await getArticles({
page: 0,
pageSize: 50,
filters: {
categories: {
slug: {
$eq: slug,
},
},
},
})

const articles = articlesResponse.data

const categoriesResponse = await getCategories()
const allCategories =
categoriesResponse?.map((category: any) => ({
name: category?.attributes?.name || '',
slug: category?.attributes?.slug || '',
})) || []

return <TopicPageComponent category={category} allCategories={allCategories} articles={articles} />
}
10 changes: 10 additions & 0 deletions apps/cow-fi/app/(learn)/learn/topics/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Topics',
description: 'All knowledge base topics',
}

export default function LayoutPage({ children }: { children: React.ReactNode }) {
return children
}
27 changes: 27 additions & 0 deletions apps/cow-fi/app/(learn)/learn/topics/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use server'

import { getArticles, getCategories } from '../../../../services/cms'
import { TopicsPageComponent } from '@/components/TopicsPageComponent'

export default async function Page() {
const categoriesResponse = await getCategories()
const articlesResponse = await getArticles()

const categories =
categoriesResponse?.map((category: any) => {
const imageUrl = category?.attributes?.image?.data?.attributes?.url || ''

return {
name: category?.attributes?.name || '',
slug: category?.attributes?.slug || '',
description: category?.attributes?.description || '',
bgColor: category?.attributes?.backgroundColor || '#fff',
textColor: category?.attributes?.textColor || '#000',
link: `/learn/topic/${category?.attributes?.slug}`,
iconColor: 'transparent',
imageUrl,
}
}) || []

return <TopicsPageComponent categories={categories} articles={articlesResponse.data} />
}
14 changes: 14 additions & 0 deletions apps/cow-fi/app/(main)/careers/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Metadata } from 'next'
import { getPageMetadata } from '@/util/getPageMetadata'

export const metadata: Metadata = {
...getPageMetadata({
title: 'Careers',
description:
'We are an ambitious, fast-growing and international team working at the forefront of DeFi. We believe that we can make markets more fair and more efficient by building the ultimate batch auction settlement layer across EVM-compatible blockchains.',
}),
}

export default function LayoutPage({ children }: { children: React.ReactNode }) {
return children
}
Loading

0 comments on commit ed152f7

Please sign in to comment.