home page strapi integration
This commit is contained in:
1 parent
91982b8c99
commit
87f4f6a1b8
8 files changed
+101
-136
No files matched your search
+11
-7
@@ -4,9 +4,10 @@ import { Meta } from 'src/components/Meta'
|
||||
import { PageGrid } from 'src/components/PageGrid'
|
||||
import { HudozkaTitle } from 'src/components/HudozkaTitle'
|
||||
import { MetaBuilder } from 'src/lib/meta'
|
||||
import { getPagesCardsByTags } from 'src/rest'
|
||||
import { NextPage } from 'next'
|
||||
import { IMeta, PageCardData, PageCardDto } from 'src/types'
|
||||
import { apiGet } from '@/next-lib'
|
||||
import { createHomeCards } from '@/remote/factory'
|
||||
|
||||
type Props = {
|
||||
title: string
|
||||
@@ -16,11 +17,16 @@ type Props = {
|
||||
|
||||
const Index: NextPage<Props> = props => {
|
||||
const items = props.items.map<PageCardData>(item => ({
|
||||
id: item.id,
|
||||
url: item.url,
|
||||
title: item.title,
|
||||
featured: item.featured,
|
||||
date: new Date(item.date),
|
||||
coverSrc: item.cover?.src,
|
||||
cover: {
|
||||
src: item.cover.src,
|
||||
width: item.cover.width,
|
||||
height: item.cover.height,
|
||||
}
|
||||
}))
|
||||
|
||||
return (
|
||||
@@ -47,11 +53,9 @@ const Index: NextPage<Props> = props => {
|
||||
}
|
||||
|
||||
export const getStaticProps = async () => {
|
||||
const items = await getPagesCardsByTags([
|
||||
'event',
|
||||
'album',
|
||||
'post',
|
||||
])
|
||||
const url = 'https://hudozka.tmshv.com/home'
|
||||
const items = await apiGet(createHomeCards)(url, [])
|
||||
|
||||
const title = 'Шлиссельбургская ДХШ'
|
||||
const meta = (new MetaBuilder())
|
||||
.setTitle(title)
|
||||
|
||||
@@ -2,7 +2,6 @@ import s from './styles.module.css'
|
||||
|
||||
import cx from 'classnames'
|
||||
import Link from 'next/link'
|
||||
import { Image } from '../Image'
|
||||
|
||||
const layoutClass = {
|
||||
simple: s.simple,
|
||||
@@ -13,11 +12,7 @@ export type CardLayout = 'simple' | 'featured'
|
||||
export type CardProps = {
|
||||
style?: React.CSSProperties
|
||||
href: string
|
||||
img: {
|
||||
alt: string
|
||||
src: string
|
||||
srcSet: string
|
||||
}
|
||||
cover: React.ReactNode
|
||||
layout: CardLayout
|
||||
}
|
||||
|
||||
@@ -26,11 +21,7 @@ export const Card: React.FC<CardProps> = props => (
|
||||
<Link href={props.href}>
|
||||
<a>
|
||||
<div className={s.image}>
|
||||
<Image
|
||||
alt={props.img.alt}
|
||||
src={props.img.src}
|
||||
srcSet={props.img.srcSet}
|
||||
/>
|
||||
{props.cover}
|
||||
</div>
|
||||
|
||||
<div className={s.body}>
|
||||
|
||||
@@ -31,18 +31,6 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
|
||||
transition: all 150ms ease-out;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.body {
|
||||
background-color: var(--color-back);
|
||||
padding: var(--size-m);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Image from 'next/image'
|
||||
import { ImageSize, PageCardData } from 'src/types'
|
||||
import { CardGrid } from '../CardGrid'
|
||||
import { Card, CardLayout } from '../Card'
|
||||
@@ -13,75 +14,53 @@ export type PageGridProps = {
|
||||
}
|
||||
|
||||
export const PageGrid: React.FC<PageGridProps> = props => {
|
||||
const [page, setPage] = useState(1)
|
||||
const i = page * 24
|
||||
const items = props.items.slice(0, i)
|
||||
const onMore = useCallback(() => {
|
||||
setPage(x => x + 1)
|
||||
}, [])
|
||||
const hasMore = i < props.items.length
|
||||
|
||||
return (
|
||||
<>
|
||||
<CardGrid
|
||||
style={{
|
||||
marginBottom: 'var(--size-m)',
|
||||
}}
|
||||
>
|
||||
{items.map((item, i) => {
|
||||
const gridColumn = item.featured ? 'span 2' : 'auto'
|
||||
const layout: CardLayout = item.featured ? 'featured' : 'simple'
|
||||
const cover = item.coverSrc ?? process.env.APP_CARD_DEFAULT_IMAGE
|
||||
const src = cover
|
||||
const srcSet = imageSrcSet(src, [ImageSize.large, ImageSize.medium, ImageSize.small])
|
||||
<CardGrid
|
||||
style={{
|
||||
marginBottom: 'var(--size-m)',
|
||||
}}
|
||||
>
|
||||
{props.items.map(item => {
|
||||
const gridColumn = item.featured ? 'span 2' : 'auto'
|
||||
const layout: CardLayout = item.featured ? 'featured' : 'simple'
|
||||
|
||||
const content = !item.featured
|
||||
? (
|
||||
<Block
|
||||
direction={'vertical'}
|
||||
>
|
||||
{item.title}
|
||||
<Spacer />
|
||||
const content = !item.featured
|
||||
? (
|
||||
<Block
|
||||
direction={'vertical'}
|
||||
>
|
||||
{item.title}
|
||||
<Spacer />
|
||||
{!item.date ? null : (
|
||||
<Date style={{
|
||||
marginTop: 'var(--size-m)',
|
||||
}}>{item.date}</Date>
|
||||
</Block>
|
||||
) : (
|
||||
item.title
|
||||
)
|
||||
|
||||
return (
|
||||
<Card
|
||||
key={i}
|
||||
href={item.url}
|
||||
img={{
|
||||
alt: item.title,
|
||||
src,
|
||||
srcSet,
|
||||
}}
|
||||
layout={layout}
|
||||
style={{
|
||||
gridColumn,
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</Card>
|
||||
)}
|
||||
</Block>
|
||||
) : (
|
||||
item.title
|
||||
)
|
||||
})}
|
||||
</CardGrid>
|
||||
<Block direction={'horizontal'} style={{
|
||||
marginTop: 'var(--size-l)'
|
||||
}}>
|
||||
<Spacer />
|
||||
<Button
|
||||
disabled={!hasMore}
|
||||
onClick={onMore}
|
||||
style={{
|
||||
flex: 2,
|
||||
}}
|
||||
>Загрузить ещё</Button>
|
||||
<Spacer />
|
||||
</Block>
|
||||
</>
|
||||
|
||||
return (
|
||||
<Card
|
||||
key={item.id}
|
||||
href={item.url}
|
||||
cover={(
|
||||
<Image
|
||||
layout={'fill'}
|
||||
objectFit={'cover'}
|
||||
src={item.cover.src}
|
||||
/>
|
||||
)}
|
||||
layout={layout}
|
||||
style={{
|
||||
gridColumn,
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</CardGrid>
|
||||
)
|
||||
}
|
||||
+27
-2
@@ -1,7 +1,7 @@
|
||||
import { getResizedUrl, imageSrc } from "@/lib/image";
|
||||
import { IPage, Token } from "@/types";
|
||||
import { IPage, PageCardDto, Token } from "@/types";
|
||||
import { asItem } from "./lib";
|
||||
import { StrapiComponent, StrapiPage } from "./types";
|
||||
import { StrapiComponent, StrapiHome, StrapiPage, StrapiPageCard } from "./types";
|
||||
|
||||
export function createPageTokens(components: StrapiComponent[]): Token[] {
|
||||
return components.map(component => {
|
||||
@@ -86,4 +86,29 @@ export function createPage(res: StrapiPage | StrapiPage[]): IPage {
|
||||
// breadcrumb?: [],
|
||||
featured: false,
|
||||
}
|
||||
}
|
||||
|
||||
function isCardFeatured(card: StrapiPageCard): boolean {
|
||||
return card.layout === 'big' || card.layout === 'medium'
|
||||
}
|
||||
|
||||
export function createHomeCards(data: StrapiHome): PageCardDto[] {
|
||||
// const cover = item.coverSrc ?? process.env.APP_CARD_DEFAULT_IMAGE
|
||||
|
||||
return data.cards.map(card => {
|
||||
return {
|
||||
id: card.id,
|
||||
// id: card.page.id,
|
||||
url: card.page.slug,
|
||||
title: card.page.title,
|
||||
featured: isCardFeatured(card),
|
||||
date: card.page.date,
|
||||
cover: {
|
||||
src: card.page.cover.url,
|
||||
width: card.page.cover.width,
|
||||
height: card.page.cover.height,
|
||||
alt: '',
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -110,4 +110,19 @@ export type StrapiPage = {
|
||||
// ],
|
||||
// "breadcrumbs": [],
|
||||
// "breadcrumbRelations": []
|
||||
}
|
||||
|
||||
export type StrapiHome = {
|
||||
id: number,
|
||||
title: string
|
||||
cards: StrapiPageCard[]
|
||||
// "created_at": "2021-02-04T04:12:38.291Z",
|
||||
// "updated_at": "2021-02-04T16:28:30.961Z",
|
||||
}
|
||||
|
||||
export type StrapiPageCard = {
|
||||
__component: 'hudozka.page-card',
|
||||
id: number,
|
||||
page: StrapiPage,
|
||||
layout: 'small' | 'medium' | 'big',
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
import { createApiUrl, requestGet, IResponseItems } from './next-lib'
|
||||
import { IPage, PageCardData, PageCardDto } from './types'
|
||||
import { queryList } from './lib/url'
|
||||
|
||||
export type QuerySlice = {
|
||||
skip: number
|
||||
limit: number
|
||||
sortBy: string
|
||||
fields?: string[]
|
||||
}
|
||||
|
||||
export async function getPagesByTags<T = IPage>(tags: string[], { skip, limit, sortBy, fields }: QuerySlice) {
|
||||
const tag = queryList('tag', tags)
|
||||
const field = queryList('field', fields ?? [])
|
||||
|
||||
const url = `/api/pages/tags?${tag}&${field}&skip=${skip}&limit=${limit}&sortBy=${sortBy}`
|
||||
const res = await requestGet<IResponseItems<T>>(createApiUrl(url), null)
|
||||
|
||||
return res?.items
|
||||
}
|
||||
|
||||
export async function getPagesCardsByTags(tags: string[]): Promise<PageCardDto[]> {
|
||||
const skip = 0
|
||||
const limit = 1000
|
||||
const fields = [
|
||||
'url',
|
||||
'title',
|
||||
'featured',
|
||||
'date',
|
||||
'cover'
|
||||
]
|
||||
|
||||
const items = await getPagesByTags<PageCardDto>(tags, { fields, skip, limit, sortBy: '-date' })
|
||||
if (!Array.isArray(items)) {
|
||||
return []
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
+3
-1
@@ -9,14 +9,16 @@ export interface IBreadcumbsPart {
|
||||
}
|
||||
|
||||
export type PageCardData = {
|
||||
id: number
|
||||
url: string
|
||||
title: string
|
||||
date: Date
|
||||
featured?: boolean
|
||||
coverSrc?: string
|
||||
cover?: ImageDefinition
|
||||
}
|
||||
|
||||
export type PageCardDto = {
|
||||
id: number
|
||||
url: string
|
||||
title: string
|
||||
featured: boolean
|
||||
|
||||
Reference in new issue
Block a user