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) => (