Skip to content

Commit 78d3f3b

Browse files
✨ redirecionando para o artigo com o slug
1 parent 589e5db commit 78d3f3b

File tree

9 files changed

+20559
-4739
lines changed

9 files changed

+20559
-4739
lines changed

package-lock.json

Lines changed: 20460 additions & 4666 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@
1313
},
1414
"dependencies": {
1515
"@hookform/resolvers": "^3.6.0",
16-
"@next/font": "^14.2.4",
1716
"@sanity/client": "^6.20.1",
18-
"@sanity/image-url": "^1.0.2",
19-
"@sanity/vision": "^3.47.1",
2017
"@types/node": "20.14.5",
2118
"@types/react": "18.3.3",
2219
"@types/react-dom": "18.3.0",
@@ -38,7 +35,6 @@
3835
},
3936
"devDependencies": {
4037
"@playwright/test": "^1.44.1",
41-
"@rocketseat/eslint-config": "^2.2.2",
42-
"@types/lodash.debounce": "^4.0.9"
38+
"@rocketseat/eslint-config": "^2.2.2"
4339
}
4440
}

src/app/artigos/Article.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export interface Article {
33
imageUrl: string
44
title: string
55
slug: string
6-
excerpt: string
6+
description: string
77
author: string
88
createdAt: string
99
}

src/app/artigos/ArticleCard.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Image from 'next/image'
2+
import Link from 'next/link'
23
import { Article } from './Article'
34

45
interface ArticleCardProps {
@@ -7,19 +8,23 @@ interface ArticleCardProps {
78

89
export function ArticleCard(props: ArticleCardProps) {
910
return (
10-
<div className="cursor-pointer col-span-1 hover:bg-gray-700 transition-all p-2 rounded-lg hover:scale-105">
11+
<Link
12+
href={`artigos/${props.article.slug}`}
13+
className="cursor-pointer col-span-1 hover:bg-gray-700 transition-all p-2 rounded-lg hover:scale-105"
14+
>
1115
<Image
1216
alt={`capa do artigo ${props.article.title}`}
1317
src={props.article.imageUrl}
18+
priority={true}
1419
height={400}
1520
width={500}
1621
className="rounded-md overflow-hidden object-cover h-24 line-clamp-2"
1722
/>
1823
<h2 className="font-bold text-lg mt-2">{props.article.title}</h2>
19-
<p className="line-clamp-3 text-gray-400">{props.article.excerpt}</p>
24+
<p className="line-clamp-3 text-gray-400">{props.article.description}</p>
2025
<p className="text-sm text-gray-400 mt-2">
2126
{props.article.author} | {props.article.createdAt}
2227
</p>
23-
</div>
28+
</Link>
2429
)
2530
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Article } from './Article'
2+
3+
export interface ArticlesRepository {
4+
findMany(): Promise<Article[]>
5+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { client } from 'programou/utils/sanity/client'
2+
import { z } from 'zod'
3+
import { Article } from './Article'
4+
import { ArticlesRepository } from './ArticlesRepository'
5+
6+
export class SanityArticlesRepository implements ArticlesRepository {
7+
async findMany(): Promise<Article[]> {
8+
const articleResponseSchema = z.array(
9+
z.object({
10+
title: z.string(),
11+
description: z.string(),
12+
author: z.object({
13+
name: z.string(),
14+
}),
15+
mainImage: z.object({
16+
asset: z.object({
17+
path: z.string(),
18+
}),
19+
}),
20+
slug: z.object({
21+
current: z.string(),
22+
}),
23+
publishedAt: z.string(),
24+
}),
25+
)
26+
const CONTENT_QUERY = `*[_type == "post"] {
27+
...,
28+
author->,
29+
mainImage {
30+
...,
31+
asset->
32+
},
33+
categories[]->,
34+
body
35+
}
36+
`
37+
const contentResponse = await client.fetch(CONTENT_QUERY)
38+
console.log(contentResponse)
39+
const articlesResponse = articleResponseSchema.parse(contentResponse)
40+
return articlesResponse.map((article) => {
41+
return {
42+
id: article.slug.current,
43+
title: article.title,
44+
description:
45+
article.description.length > 120
46+
? article.description.substring(0, 120).concat('...')
47+
: article.description,
48+
author: article.author.name,
49+
createdAt: article.publishedAt,
50+
imageUrl: 'https://cdn.sanity.io/'.concat(article.mainImage.asset.path),
51+
slug: article.slug.current,
52+
} as Article
53+
})
54+
}
55+
}

src/app/artigos/[slug]/page.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
interface ArticlePageProps {
2+
params: {
3+
slug: string
4+
}
5+
}
6+
7+
export default function ArticlePage(props: ArticlePageProps) {
8+
return (
9+
<div>
10+
<h1>{props.params.slug}</h1>
11+
</div>
12+
)
13+
}

src/app/artigos/page.tsx

Lines changed: 16 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,38 @@
11
'use client'
22

3-
import { client } from 'programou/utils/sanity/client'
4-
import { useState } from 'react'
5-
import { z } from 'zod'
3+
import { useEffect, useState } from 'react'
64
import { Article } from './Article'
75
import { ArticleList } from './ArticleList'
86
import { EmptyState } from './EmptyState'
7+
import { SanityArticlesRepository } from './SanityArticlesRepository'
98
import { SeachInputField, SearchForm } from './SeachInputField'
109

11-
interface ArticlesRepository {
12-
findMany(): Promise<Article[]>
13-
}
14-
15-
class SanityArticlesRepository implements ArticlesRepository {
16-
async findMany(): Promise<Article[]> {
17-
const articleResponseSchema = z.array(
18-
z.object({
19-
title: z.string(),
20-
author: z.object({
21-
name: z.string(),
22-
}),
23-
mainImage: z.object({
24-
asset: z.object({
25-
path: z.string(),
26-
}),
27-
}),
28-
slug: z.object({
29-
current: z.string(),
30-
}),
31-
publishedAt: z.string(),
32-
}),
33-
)
34-
const CONTENT_QUERY = `*[_type == "post"] {
35-
...,
36-
author->,
37-
mainImage {
38-
...,
39-
asset->
40-
},
41-
categories[]->,
42-
body
43-
}
44-
`
45-
const contentResponse = await client.fetch(CONTENT_QUERY)
46-
const articlesResponse = articleResponseSchema.parse(contentResponse)
47-
return articlesResponse.map((article) => {
48-
return {
49-
id: article.slug.current,
50-
title: article.title,
51-
excerpt: article.title.substring(0, 40).concat('...'),
52-
author: article.author.name,
53-
createdAt: article.publishedAt,
54-
imageUrl: 'https://cdn.sanity.io/'.concat(article.mainImage.asset.path),
55-
slug: article.slug.current,
56-
} as Article
57-
})
58-
}
59-
}
60-
6110
const articlesRepository = new SanityArticlesRepository()
6211

6312
export default function ArticlePage() {
6413
const [allArticles, setAllArticles] = useState<Article[]>([])
6514
const [articles, setArticles] = useState(allArticles)
6615

67-
articlesRepository.findMany().then((articles) => {
68-
setAllArticles(articles)
69-
setArticles(articles)
70-
})
16+
useEffect(() => {
17+
articlesRepository.findMany().then((articles) => {
18+
setAllArticles(articles)
19+
setArticles(articles)
20+
})
21+
}, [setAllArticles, setArticles])
7122

7223
function submitActionHandler(search: SearchForm) {
7324
if (search.query.length === 0) {
7425
setArticles(allArticles)
7526
} else {
7627
setArticles(
77-
allArticles.filter(
78-
(article) =>
79-
article.title.includes(search.query) ||
80-
article.excerpt.includes(search.query) ||
81-
article.author.includes(search.query),
82-
),
28+
allArticles.filter((article) => {
29+
const searchLower = search.query.toLowerCase()
30+
return (
31+
article.title.toLowerCase().includes(searchLower) ||
32+
article.description.toLowerCase().includes(searchLower) ||
33+
article.author.toLowerCase().includes(searchLower)
34+
)
35+
}),
8336
)
8437
}
8538
}

src/app/layout.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import React from 'react'
21
import './globals.css'
32

43
// eslint-disable-next-line camelcase

0 commit comments

Comments
 (0)