From c300b2501d1184e1cb5a52f08a8b00963f224e76 Mon Sep 17 00:00:00 2001 From: Riccardo Senica <46839416+RiccardoSenica@users.noreply.github.com> Date: Sat, 23 Nov 2024 09:13:15 +0100 Subject: [PATCH] chore: code cleaning (#21) --- app/api/confirmation/route.ts | 11 +- app/api/import/route.ts | 14 +- app/api/mailing/route.ts | 24 +- app/api/news/route.ts | 9 +- app/api/subscribe/route.ts | 22 +- app/api/unsubscribe/route.ts | 17 +- app/confirmation/page.tsx | 16 +- app/layout.tsx | 4 +- app/page.tsx | 14 +- app/privacy/page.tsx | 12 +- app/unsubscribe/page.tsx | 14 +- components/CustomCard.tsx | 8 +- components/ErrorMessage.tsx | 4 +- components/Footer.tsx | 4 +- components/SchemaOrg.tsx | 4 +- components/email/Confirmation.tsx | 8 +- components/email/Newsletter.tsx | 10 +- components/email/Template.tsx | 8 +- components/email/Unsubscribe.tsx | 8 +- components/email/components/Footer.tsx | 4 +- components/email/components/Note.tsx | 4 +- components/tiles/Tiles.tsx | 6 +- components/tiles/components/Tile.tsx | 6 +- components/tiles/components/TileContent.tsx | 6 +- hooks/useFormField.tsx | 4 +- utils/{anthropic.ts => anthropicClient.ts} | 2 +- .../{apiResponse.ts => formatApiResponse.ts} | 2 +- ...tterSubject.ts => getNewsletterSubject.ts} | 2 +- utils/{sender.ts => resendClient.ts} | 0 utils/summarize.ts | 4 +- yarn.lock | 1524 ++++++++--------- 31 files changed, 903 insertions(+), 872 deletions(-) rename utils/{anthropic.ts => anthropicClient.ts} (89%) rename utils/{apiResponse.ts => formatApiResponse.ts} (68%) rename utils/{newsletterSubject.ts => getNewsletterSubject.ts} (96%) rename utils/{sender.ts => resendClient.ts} (100%) diff --git a/app/api/confirmation/route.ts b/app/api/confirmation/route.ts index e7dab55..fed56ca 100644 --- a/app/api/confirmation/route.ts +++ b/app/api/confirmation/route.ts @@ -1,5 +1,5 @@ import prisma from '@prisma/prisma'; -import { ApiResponse } from '@utils/apiResponse'; +import { formatApiResponse } from '@utils/formatApiResponse'; import { BAD_REQUEST, INTERNAL_SERVER_ERROR, @@ -21,7 +21,7 @@ export async function POST(request: NextRequest) { const body = await request.json(); const validation = ConfirmationSchema.safeParse(body); if (!validation.success || !validation.data.code) { - return ApiResponse(STATUS_BAD_REQUEST, BAD_REQUEST); + return formatApiResponse(STATUS_BAD_REQUEST, BAD_REQUEST); } const user = await prisma.user.findUnique({ @@ -53,10 +53,13 @@ export async function POST(request: NextRequest) { message: `Thank you for confirming the subscription, ${user.email}!` }; - return ApiResponse(STATUS_OK, message); + return formatApiResponse(STATUS_OK, message); } } catch (error) { console.error(error); - return ApiResponse(STATUS_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR); + return formatApiResponse( + STATUS_INTERNAL_SERVER_ERROR, + INTERNAL_SERVER_ERROR + ); } } diff --git a/app/api/import/route.ts b/app/api/import/route.ts index 43c436b..04523a6 100644 --- a/app/api/import/route.ts +++ b/app/api/import/route.ts @@ -1,5 +1,5 @@ import prisma from '@prisma/prisma'; -import { ApiResponse } from '@utils/apiResponse'; +import { formatApiResponse } from '@utils/formatApiResponse'; import { INTERNAL_SERVER_ERROR, STATUS_INTERNAL_SERVER_ERROR, @@ -15,7 +15,7 @@ export async function GET(request: NextRequest) { if ( request.headers.get('Authorization') !== `Bearer ${process.env.CRON_SECRET}` ) { - return ApiResponse(STATUS_UNAUTHORIZED, 'Unauthorized'); + return formatApiResponse(STATUS_UNAUTHORIZED, 'Unauthorized'); } try { @@ -76,9 +76,15 @@ export async function GET(request: NextRequest) { }); } - return ApiResponse(STATUS_OK, `Imported ${newsPromises.length} news.`); + return formatApiResponse( + STATUS_OK, + `Imported ${newsPromises.length} news.` + ); } catch (error) { console.error(error); - return ApiResponse(STATUS_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR); + return formatApiResponse( + STATUS_INTERNAL_SERVER_ERROR, + INTERNAL_SERVER_ERROR + ); } } diff --git a/app/api/mailing/route.ts b/app/api/mailing/route.ts index db5c213..643db28 100644 --- a/app/api/mailing/route.ts +++ b/app/api/mailing/route.ts @@ -1,7 +1,7 @@ -import NewsletterTemplate from '@components/email/Newsletter'; +import { NewsletterTemplate } from '@components/email/Newsletter'; import prisma from '@prisma/prisma'; -import { ApiResponse } from '@utils/apiResponse'; -import { sender } from '@utils/sender'; +import { formatApiResponse } from '@utils/formatApiResponse'; +import { sender } from '@utils/resendClient'; import { INTERNAL_SERVER_ERROR, STATUS_INTERNAL_SERVER_ERROR, @@ -17,7 +17,7 @@ export async function GET(request: NextRequest) { if ( request.headers.get('Authorization') !== `Bearer ${process.env.CRON_SECRET}` ) { - return ApiResponse(STATUS_UNAUTHORIZED, 'Unauthorized'); + return formatApiResponse(STATUS_UNAUTHORIZED, 'Unauthorized'); } if (!process.env.NEWS_TO_USE) { @@ -52,7 +52,7 @@ export async function GET(request: NextRequest) { console.info(`Found ${users.length} users to mail to.`); if (users.length === 0) { - return ApiResponse(STATUS_OK, 'No user to mail to.'); + return formatApiResponse(STATUS_OK, 'No user to mail to.'); } const news = await prisma.news.findMany({ @@ -70,7 +70,7 @@ export async function GET(request: NextRequest) { console.info(`Found ${news.length} news to include in the newsletter.`); if (news.length === 0) { - return ApiResponse(STATUS_OK, 'No news to include in newsletter.'); + return formatApiResponse(STATUS_OK, 'No news to include in newsletter.'); } const validRankedNews = news.sort((a, b) => b.score - a.score); @@ -83,7 +83,10 @@ export async function GET(request: NextRequest) { ); if (!sent) { - return ApiResponse(STATUS_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR); + return formatApiResponse( + STATUS_INTERNAL_SERVER_ERROR, + INTERNAL_SERVER_ERROR + ); } // update users so they don't get the newsletter again @@ -98,12 +101,15 @@ export async function GET(request: NextRequest) { } }); - return ApiResponse( + return formatApiResponse( STATUS_OK, `Newsletter sent to ${users.length} addresses.` ); } catch (error) { console.error(error); - return ApiResponse(STATUS_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR); + return formatApiResponse( + STATUS_INTERNAL_SERVER_ERROR, + INTERNAL_SERVER_ERROR + ); } } diff --git a/app/api/news/route.ts b/app/api/news/route.ts index 875b475..748ff43 100644 --- a/app/api/news/route.ts +++ b/app/api/news/route.ts @@ -1,5 +1,5 @@ import prisma from '@prisma/prisma'; -import { ApiResponse } from '@utils/apiResponse'; +import { formatApiResponse } from '@utils/formatApiResponse'; import { INTERNAL_SERVER_ERROR, STATUS_INTERNAL_SERVER_ERROR, @@ -21,10 +21,13 @@ export async function GET() { }); if (news) { - return ApiResponse(STATUS_OK, news); + return formatApiResponse(STATUS_OK, news); } } catch (error) { console.error(error); - return ApiResponse(STATUS_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR); + return formatApiResponse( + STATUS_INTERNAL_SERVER_ERROR, + INTERNAL_SERVER_ERROR + ); } } diff --git a/app/api/subscribe/route.ts b/app/api/subscribe/route.ts index d362965..75319fb 100644 --- a/app/api/subscribe/route.ts +++ b/app/api/subscribe/route.ts @@ -1,7 +1,7 @@ -import ConfirmationTemplate from '@components/email/Confirmation'; +import { ConfirmationTemplate } from '@components/email/Confirmation'; import prisma from '@prisma/prisma'; -import { ApiResponse } from '@utils/apiResponse'; -import { sender } from '@utils/sender'; +import { formatApiResponse } from '@utils/formatApiResponse'; +import { sender } from '@utils/resendClient'; import { BAD_REQUEST, INTERNAL_SERVER_ERROR, @@ -25,7 +25,7 @@ export async function POST(request: NextRequest) { const validation = SubscribeFormSchema.safeParse(body); if (!validation.success) { - return ApiResponse(STATUS_BAD_REQUEST, BAD_REQUEST); + return formatApiResponse(STATUS_BAD_REQUEST, BAD_REQUEST); } const { email } = validation.data; @@ -73,7 +73,7 @@ export async function POST(request: NextRequest) { message: `Thank you for subscribing!` }; - return ApiResponse(STATUS_OK, message); + return formatApiResponse(STATUS_OK, message); } else if (user && !user.confirmed) { await prisma.user.update({ where: { @@ -106,7 +106,10 @@ export async function POST(request: NextRequest) { const sent = await sender([email], ConfirmationTemplate(code)); if (!sent) { - return ApiResponse(STATUS_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR); + return formatApiResponse( + STATUS_INTERNAL_SERVER_ERROR, + INTERNAL_SERVER_ERROR + ); } const message: ResponseType = { @@ -114,9 +117,12 @@ export async function POST(request: NextRequest) { message: `Thank you! You will now receive an email to ${email} to confirm the subscription.` }; - return ApiResponse(STATUS_OK, message); + return formatApiResponse(STATUS_OK, message); } catch (error) { console.error(error); - return ApiResponse(STATUS_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR); + return formatApiResponse( + STATUS_INTERNAL_SERVER_ERROR, + INTERNAL_SERVER_ERROR + ); } } diff --git a/app/api/unsubscribe/route.ts b/app/api/unsubscribe/route.ts index 8b72cc1..3c06f8c 100644 --- a/app/api/unsubscribe/route.ts +++ b/app/api/unsubscribe/route.ts @@ -1,7 +1,7 @@ -import UnsubscribeTemplate from '@components/email/Unsubscribe'; +import { UnsubscribeTemplate } from '@components/email/Unsubscribe'; import prisma from '@prisma/prisma'; -import { ApiResponse } from '@utils/apiResponse'; -import { sender } from '@utils/sender'; +import { formatApiResponse } from '@utils/formatApiResponse'; +import { sender } from '@utils/resendClient'; import { BAD_REQUEST, INTERNAL_SERVER_ERROR, @@ -23,7 +23,7 @@ export async function POST(request: NextRequest) { const body = await request.json(); const validation = UnsubscribeFormSchema.safeParse(body); if (!validation.success) { - return ApiResponse(STATUS_BAD_REQUEST, BAD_REQUEST); + return formatApiResponse(STATUS_BAD_REQUEST, BAD_REQUEST); } const { email } = validation.data; @@ -55,7 +55,7 @@ export async function POST(request: NextRequest) { const sent = await sender([email], UnsubscribeTemplate()); if (!sent) { - return ApiResponse( + return formatApiResponse( STATUS_INTERNAL_SERVER_ERROR, 'Internal server error' ); @@ -67,9 +67,12 @@ export async function POST(request: NextRequest) { message: `${email} unsubscribed.` }; - return ApiResponse(STATUS_OK, message); + return formatApiResponse(STATUS_OK, message); } catch (error) { console.error(error); - return ApiResponse(STATUS_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR); + return formatApiResponse( + STATUS_INTERNAL_SERVER_ERROR, + INTERNAL_SERVER_ERROR + ); } } diff --git a/app/confirmation/page.tsx b/app/confirmation/page.tsx index 695187a..ba4c324 100644 --- a/app/confirmation/page.tsx +++ b/app/confirmation/page.tsx @@ -1,13 +1,13 @@ 'use client'; import { CardDescription } from '@components/Card'; -import CustomCard from '@components/CustomCard'; -import Schema from '@components/SchemaOrg'; +import { CustomCard } from '@components/CustomCard'; +import { SchemaOrg } from '@components/SchemaOrg'; import { ResponseType } from '@utils/validationSchemas'; import { useRouter, useSearchParams } from 'next/navigation'; import { Suspense, useEffect, useState } from 'react'; -function ConfirmationPage() { +const ConfirmationPage = () => { const router = useRouter(); const searchParams = useSearchParams(); const [loading, setLoading] = useState(true); @@ -78,9 +78,9 @@ function ConfirmationPage() { footer={false} /> ); -} +}; -export default function Confirmation() { +const Confirmation = () => { const schema = { '@context': 'https://schema.org', '@type': 'WebSite', @@ -91,10 +91,12 @@ export default function Confirmation() { return ( <> - + Loading...}> ); -} +}; + +export default Confirmation; diff --git a/app/layout.tsx b/app/layout.tsx index 611d837..d212806 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,4 +1,4 @@ -import Tiles from '@components/tiles/Tiles'; +import { Tiles } from '@components/tiles/Tiles'; import { cn } from '@utils/cn'; import { Analytics } from '@vercel/analytics/react'; import type { Metadata } from 'next'; @@ -6,7 +6,7 @@ import { Inter as FontSans } from 'next/font/google'; import './globals.css'; export const metadata: Metadata = { - title: 'Hacker News newsletter by FromPixels', + title: `Hacker News newsletter by ${process.env.NEXT_PUBLIC_BRAND_NAME}`, description: 'Newsletter delivering the best posts from Hacker News', keywords: 'newsletter, hackernews, technology, coding, programming, news' }; diff --git a/app/page.tsx b/app/page.tsx index 06d2612..97b741b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,12 +2,12 @@ import { Button } from '@components/Button'; import { CardDescription } from '@components/Card'; -import CustomCard from '@components/CustomCard'; -import ErrorMessage from '@components/ErrorMessage'; +import { CustomCard } from '@components/CustomCard'; +import { ErrorMessage } from '@components/ErrorMessage'; import { FormControl } from '@components/form/FormControl'; import { FormMessage } from '@components/form/FormMessage'; import { Input } from '@components/Input'; -import Schema from '@components/SchemaOrg'; +import { SchemaOrg } from '@components/SchemaOrg'; import { FormField } from '@contexts/FormField/FormFieldProvider'; import { FormItem } from '@contexts/FormItem/FormItemProvider'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -19,7 +19,7 @@ import { import { useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -export default function Home() { +export const Home = () => { const [completed, setCompleted] = useState(false); const [message, setMessage] = useState(''); const [error, setError] = useState(false); @@ -119,7 +119,7 @@ export default function Home() { return ( <> - + ); -} +}; + +export default Home; diff --git a/app/privacy/page.tsx b/app/privacy/page.tsx index b7631b7..66bf321 100644 --- a/app/privacy/page.tsx +++ b/app/privacy/page.tsx @@ -1,10 +1,10 @@ 'use client'; -import CustomCard from '@components/CustomCard'; -import Schema from '@components/SchemaOrg'; +import { CustomCard } from '@components/CustomCard'; +import { SchemaOrg } from '@components/SchemaOrg'; import Link from 'next/link'; -export default function Privacy() { +const Privacy = () => { const schema = { '@context': 'https://schema.org', '@type': 'WebSite', @@ -449,7 +449,7 @@ export default function Privacy() { return ( <> - + ); -} +}; + +export default Privacy; diff --git a/app/unsubscribe/page.tsx b/app/unsubscribe/page.tsx index 3f23c15..acf1a9e 100644 --- a/app/unsubscribe/page.tsx +++ b/app/unsubscribe/page.tsx @@ -2,12 +2,12 @@ import { Button } from '@components/Button'; import { CardDescription } from '@components/Card'; -import CustomCard from '@components/CustomCard'; -import ErrorMessage from '@components/ErrorMessage'; +import { CustomCard } from '@components/CustomCard'; +import { ErrorMessage } from '@components/ErrorMessage'; import { FormControl } from '@components/form/FormControl'; import { FormMessage } from '@components/form/FormMessage'; import { Input } from '@components/Input'; -import Schema from '@components/SchemaOrg'; +import { SchemaOrg } from '@components/SchemaOrg'; import { FormField } from '@contexts/FormField/FormFieldProvider'; import { FormItem } from '@contexts/FormItem/FormItemProvider'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -19,7 +19,7 @@ import { import { useEffect, useRef, useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -export default function Unsubscribe() { +const Unsubscribe = () => { const [completed, setCompleted] = useState(false); const [message, setMessage] = useState(''); const [error, setError] = useState(false); @@ -122,7 +122,7 @@ export default function Unsubscribe() { return ( <> - + ); -} +}; + +export default Unsubscribe; diff --git a/components/CustomCard.tsx b/components/CustomCard.tsx index 014a307..3904950 100644 --- a/components/CustomCard.tsx +++ b/components/CustomCard.tsx @@ -7,7 +7,7 @@ import { CardHeader, CardTitle } from './Card'; -import Footer from './Footer'; +import { Footer } from './Footer'; interface CardProps { title: string; @@ -17,13 +17,13 @@ interface CardProps { footer?: boolean; } -export default function CustomCard({ +export const CustomCard = ({ title, description, content, className, footer = true -}: CardProps) { +}: CardProps) => { const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { @@ -53,4 +53,4 @@ export default function CustomCard({ ); -} +}; diff --git a/components/ErrorMessage.tsx b/components/ErrorMessage.tsx index 9362c99..4157aa2 100644 --- a/components/ErrorMessage.tsx +++ b/components/ErrorMessage.tsx @@ -1,5 +1,5 @@ 'use client'; -export default function ErrorMessage() { +export const ErrorMessage = () => { return 'Oops. Something went wrong. Please try later :('; -} +}; diff --git a/components/Footer.tsx b/components/Footer.tsx index 3e2390b..03ef8ac 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -5,7 +5,7 @@ import CustomLink from './CustomLink'; const links = [{ name: 'Subscribe', path: '/' }]; -export default function Footer() { +export const Footer = () => { const pathname = usePathname(); return ( @@ -37,4 +37,4 @@ export default function Footer() { )} ); -} +}; diff --git a/components/SchemaOrg.tsx b/components/SchemaOrg.tsx index 33187d9..7d9477a 100644 --- a/components/SchemaOrg.tsx +++ b/components/SchemaOrg.tsx @@ -1,7 +1,7 @@ import Head from 'next/head'; // eslint-disable-next-line @typescript-eslint/no-explicit-any -const SchemaOrg = ({ schema }: Record) => ( +export const SchemaOrg = ({ schema }: Record) => (