-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #200 from svobik7/feature/catch-all-non-optional
feat(routes): added support for catch all non-optional routes
- Loading branch information
Showing
24 changed files
with
440 additions
and
97 deletions.
There are no files selected for viewing
10 changes: 10 additions & 0 deletions
10
examples/basic/src/features/blog/utils/getBookLinkParams.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import type { BookTranslation } from 'src/server/db/types' | ||
import { getBooksDetailHref } from 'src/server/router' | ||
|
||
export function getBookLinkParams(book: BookTranslation) { | ||
return { | ||
locale: book.locale, | ||
name: book.title, | ||
href: getBooksDetailHref(book), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import type { Metadata } from 'next' | ||
import type { Book } from 'src/server/db/types' | ||
import { getBookTranslation } from './getBookTranslation' | ||
|
||
export function getBookMetadata(book: Book, locale: string): Metadata { | ||
const bookTranslation = getBookTranslation({ book, locale }) | ||
|
||
return { | ||
title: bookTranslation.title, | ||
description: bookTranslation.content?.slice(0, 255), | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
examples/basic/src/features/blog/utils/getBookTranslation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import type { Book, BookTranslation } from '../../../server/db/types' | ||
import { getTranslationFactory } from '../../common/utils/getTranslation' | ||
|
||
type GetBookTranslationProps = { | ||
book: Book | ||
locale: string | ||
} | ||
|
||
export function getBookTranslation({ book, locale }: GetBookTranslationProps) { | ||
const translate = getTranslationFactory(locale) | ||
|
||
return { | ||
...book, | ||
title: translate(book, 'title'), | ||
content: translate(book, 'content'), | ||
slug: translate(book, 'slug'), | ||
locale, | ||
} | ||
} | ||
|
||
export function getAllBookTranslations(book: Book) { | ||
return book.slug.map(({ locale }) => getBookTranslation({ book, locale })) | ||
} | ||
|
||
export function getBookTranslationFactory(locale: string) { | ||
return (book: Book): BookTranslation => getBookTranslation({ locale, book }) | ||
} |
21 changes: 9 additions & 12 deletions
21
...res/products/components/ProductDetail.tsx → ...src/features/common/components/Detail.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import type { BookTranslation } from 'src/server/db/types' | ||
import { ListItem, ListItemProps } from './ListItem' | ||
|
||
type Item = ListItemProps & { id: string | number } | ||
|
||
type ListProps = { | ||
items: Item[] | ||
} | ||
|
||
export function List({ items }: ListProps) { | ||
return ( | ||
<div className="mx-auto grid max-w-2xl grid-cols-1 gap-4 lg:mx-0 lg:max-w-none lg:grid-cols-3"> | ||
{items.map((item) => ( | ||
<ListItem key={item.id} {...item} /> | ||
))} | ||
</div> | ||
) | ||
} |
24 changes: 13 additions & 11 deletions
24
.../products/components/ProductsListItem.tsx → ...c/features/common/components/ListItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 0 additions & 16 deletions
16
examples/basic/src/features/products/components/ProductsList.tsx
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import type { Metadata } from 'next' | ||
import type { | ||
GeneratePageMetadataProps, | ||
GenerateStaticParamsProps, | ||
PageProps, | ||
} from 'next-roots' | ||
import Link from 'next/link' | ||
import { notFound, redirect } from 'next/navigation' | ||
import { getBookLinkParams } from 'src/features/blog/utils/getBookLinkParams' | ||
import { getBookMetadata } from 'src/features/blog/utils/getBookMetadata' | ||
import { | ||
getAllBookTranslations, | ||
getBookTranslation, | ||
} from 'src/features/blog/utils/getBookTranslation' | ||
import { Detail } from 'src/features/common/components/Detail' | ||
import { Links } from 'src/features/common/components/Links' | ||
import { fetchBookBySlug, fetchBooks, fetchProductBySlug } from 'src/server/db' | ||
import { getBooksDetailHref, getHomeHref, router } from 'src/server/router' | ||
import { getDictionary } from 'src/server/utils/getDictionary' | ||
|
||
type BookParam = { slugs: string[] } | ||
|
||
export default async function BookPage({ | ||
params, | ||
pageHref, | ||
}: PageProps<BookParam>) { | ||
const pageLocale = router.getLocaleFromHref(pageHref) | ||
const t = await getDictionary(pageLocale) | ||
|
||
const book = await fetchBookBySlug(params.slugs) | ||
|
||
if (!book) { | ||
return notFound() | ||
} | ||
|
||
const allBookTranslations = getAllBookTranslations(book) | ||
const currentBookTranslation = getBookTranslation({ | ||
book, | ||
locale: pageLocale, | ||
}) | ||
|
||
if (!currentBookTranslation) { | ||
return notFound() | ||
} | ||
|
||
const href = getBooksDetailHref(currentBookTranslation) | ||
|
||
if (pageHref !== href) { | ||
return redirect(href) | ||
} | ||
|
||
return ( | ||
<Detail | ||
title={currentBookTranslation.title} | ||
content={currentBookTranslation.content} | ||
alternatives={ | ||
<Links | ||
header={t('common.NotYourLanguage?')} | ||
items={allBookTranslations.map(getBookLinkParams)} | ||
/> | ||
} | ||
buttonBack={ | ||
<Link | ||
href={getHomeHref(currentBookTranslation.locale)} | ||
role="button" | ||
className="rounded bg-indigo-600 px-4 py-2 text-base font-semibold leading-7 text-white" | ||
> | ||
{t('article.BtnBack')} | ||
</Link> | ||
} | ||
/> | ||
) | ||
} | ||
|
||
export async function generateMetadata({ | ||
pageHref, | ||
params, | ||
}: GeneratePageMetadataProps<BookParam>): Promise<Metadata> { | ||
const pageLocale = router.getLocaleFromHref(pageHref) | ||
const t = await getDictionary(pageLocale) | ||
|
||
const book = await fetchProductBySlug(params.slugs) | ||
|
||
if (!book) { | ||
return {} | ||
} | ||
|
||
return getBookMetadata(book, pageLocale) | ||
} | ||
|
||
export async function generateStaticParams({ | ||
pageLocale, | ||
}: GenerateStaticParamsProps) { | ||
const books = await fetchBooks() | ||
|
||
return books | ||
.map((book) => ({ | ||
slugs: book.slug | ||
.find((slug) => slug.locale === pageLocale) | ||
?.value.split('/'), | ||
})) | ||
.filter((book) => book.slugs) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports.routeNames = [ | ||
{ locale: 'en', path: 'books' }, | ||
{ locale: 'cs', path: 'knihy' }, | ||
{ locale: 'es', path: 'libros' }, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import type { Metadata } from 'next' | ||
import type { GeneratePageMetadataProps, PageProps } from 'next-roots' | ||
import { getBookTranslationFactory } from 'src/features/blog/utils/getBookTranslation' | ||
import { List } from 'src/features/common/components/List' | ||
import { fetchBooks } from 'src/server/db' | ||
import { getBooksDetailHref, router } from 'src/server/router' | ||
import { getDictionary } from 'src/server/utils/getDictionary' | ||
|
||
export default async function BooksPage({ pageHref }: PageProps) { | ||
const pageLocale = router.getLocaleFromHref(pageHref) | ||
const translateBook = getBookTranslationFactory(pageLocale) | ||
|
||
const books = await fetchBooks() | ||
|
||
return ( | ||
<List | ||
items={books.map(translateBook).map((book) => ({ | ||
id: book.id, | ||
title: book.title, | ||
href: getBooksDetailHref(book), | ||
content: book.content, | ||
createdAt: book.createdAt, | ||
}))} | ||
/> | ||
) | ||
} | ||
|
||
export async function generateMetadata({ | ||
pageHref, | ||
}: GeneratePageMetadataProps): Promise<Metadata> { | ||
const pageLocale = router.getLocaleFromHref(pageHref) | ||
const t = await getDictionary(pageLocale) | ||
|
||
return { title: t('books.title'), description: t('books.content') } | ||
} |
Oops, something went wrong.