diff --git a/app/api/newsletter/subscribe.ts b/app/api/newsletter/subscribe.ts index cb15a40..20ad8f3 100644 --- a/app/api/newsletter/subscribe.ts +++ b/app/api/newsletter/subscribe.ts @@ -13,10 +13,7 @@ const bodySchema = zod.object({ email: zod.string().email(), }); -export default async function subscribeToNewsletter( - req: BlitzApiRequest, - res: BlitzApiResponse, -) { +export default async function subscribeToNewsletter(req: BlitzApiRequest, res: BlitzApiResponse) { if (req.method !== "POST") { const statusCode = 405; const apiError: ApiError = { diff --git a/app/auth/components/login-form.tsx b/app/auth/components/login-form.tsx index 4d7154a..1444712 100644 --- a/app/auth/components/login-form.tsx +++ b/app/auth/components/login-form.tsx @@ -30,20 +30,14 @@ export const LoginForm = (props: LoginFormProps) => { } else { return { [FORM_ERROR]: - "Sorry, we had an unexpected error. Please try again. - " + - error.toString(), + "Sorry, we had an unexpected error. Please try again. - " + error.toString(), }; } } }} > - +
Forgot your password? diff --git a/app/auth/components/signup-form.tsx b/app/auth/components/signup-form.tsx index 988ec33..594fe16 100644 --- a/app/auth/components/signup-form.tsx +++ b/app/auth/components/signup-form.tsx @@ -35,12 +35,7 @@ export const SignupForm = (props: SignupFormProps) => { }} > - +
); diff --git a/app/auth/mutations/forgot-password.test.ts b/app/auth/mutations/forgot-password.test.ts index 1ceeb83..ff0b068 100644 --- a/app/auth/mutations/forgot-password.test.ts +++ b/app/auth/mutations/forgot-password.test.ts @@ -17,9 +17,7 @@ jest.mock("preview-email", () => jest.fn()); describe.skip("forgotPassword mutation", () => { it("does not throw error if user doesn't exist", async () => { - await expect( - forgotPassword({ email: "no-user@email.com" }, {} as Ctx), - ).resolves.not.toThrow(); + await expect(forgotPassword({ email: "no-user@email.com" }, {} as Ctx)).resolves.not.toThrow(); }); it("works correctly", async () => { diff --git a/app/auth/mutations/reset-password.test.ts b/app/auth/mutations/reset-password.test.ts index d7f0b04..5407d4f 100644 --- a/app/auth/mutations/reset-password.test.ts +++ b/app/auth/mutations/reset-password.test.ts @@ -58,17 +58,11 @@ describe.skip("resetPassword mutation", () => { // Expired token await expect( - resetPassword( - { token: expiredToken, password: newPassword, passwordConfirmation: newPassword }, - mockCtx, - ), + resetPassword({ token: expiredToken, password: newPassword, passwordConfirmation: newPassword }, mockCtx), ).rejects.toThrowError(); // Good token - await resetPassword( - { token: goodToken, password: newPassword, passwordConfirmation: newPassword }, - mockCtx, - ); + await resetPassword({ token: goodToken, password: newPassword, passwordConfirmation: newPassword }, mockCtx); // Delete's the token const numberOfTokens = await db.token.count({ where: { userId: user.id } }); @@ -76,8 +70,6 @@ describe.skip("resetPassword mutation", () => { // Updates user's password const updatedUser = await db.user.findFirst({ where: { id: user.id } }); - expect(await SecurePassword.verify(updatedUser!.hashedPassword, newPassword)).toBe( - SecurePassword.VALID, - ); + expect(await SecurePassword.verify(updatedUser!.hashedPassword, newPassword)).toBe(SecurePassword.VALID); }); }); diff --git a/app/auth/pages/forgot-password.tsx b/app/auth/pages/forgot-password.tsx index 039f1ca..c5f7b39 100644 --- a/app/auth/pages/forgot-password.tsx +++ b/app/auth/pages/forgot-password.tsx @@ -17,10 +17,7 @@ const ForgotPasswordPage: BlitzPage = () => { {isSuccess ? (

Request Submitted

-

- If your email is in our system, you will receive instructions to reset your - password shortly. -

+

If your email is in our system, you will receive instructions to reset your password shortly.

) : (
{ await forgotPasswordMutation(values); } catch (error) { return { - [FORM_ERROR]: - "Sorry, we had an unexpected error. Please try again.", + [FORM_ERROR]: "Sorry, we had an unexpected error. Please try again.", }; } }} @@ -47,8 +43,6 @@ const ForgotPasswordPage: BlitzPage = () => { ForgotPasswordPage.redirectAuthenticatedTo = Routes.Messages(); -ForgotPasswordPage.getLayout = (page) => ( - {page} -); +ForgotPasswordPage.getLayout = (page) => {page}; export default ForgotPasswordPage; diff --git a/app/auth/pages/reset-password.tsx b/app/auth/pages/reset-password.tsx index 3c9ac01..ed3c810 100644 --- a/app/auth/pages/reset-password.tsx +++ b/app/auth/pages/reset-password.tsx @@ -41,19 +41,14 @@ const ResetPasswordPage: BlitzPage = () => { }; } else { return { - [FORM_ERROR]: - "Sorry, we had an unexpected error. Please try again.", + [FORM_ERROR]: "Sorry, we had an unexpected error. Please try again.", }; } } }} > - + )} diff --git a/app/core/components/labeled-text-field.tsx b/app/core/components/labeled-text-field.tsx index aaed95c..5c53d1b 100644 --- a/app/core/components/labeled-text-field.tsx +++ b/app/core/components/labeled-text-field.tsx @@ -17,9 +17,7 @@ export const LabeledTextField = forwardRef diff --git a/app/core/layouts/layout/index.tsx b/app/core/layouts/layout/index.tsx index 8f564e6..1132349 100644 --- a/app/core/layouts/layout/index.tsx +++ b/app/core/layouts/layout/index.tsx @@ -23,12 +23,7 @@ type Props = { const logger = appLogger.child({ module: "Layout" }); -const Layout: FunctionComponent = ({ - children, - title, - pageTitle = title, - hideFooter = false, -}) => { +const Layout: FunctionComponent = ({ children, title, pageTitle = title, hideFooter = false }) => { return ( <> {pageTitle ? ( @@ -60,13 +55,7 @@ type ErrorBoundaryState = errorMessage: string; }; -const blitzErrors = [ - RedirectError, - AuthenticationError, - AuthorizationError, - CSRFTokenMismatchError, - NotFoundError, -]; +const blitzErrors = [RedirectError, AuthenticationError, AuthorizationError, CSRFTokenMismatchError, NotFoundError]; const ErrorBoundary = withRouter( class ErrorBoundary extends Component { diff --git a/app/messages/api/queue/insert-incoming-message.ts b/app/messages/api/queue/insert-incoming-message.ts index 1f7f7ef..98d5c54 100644 --- a/app/messages/api/queue/insert-incoming-message.ts +++ b/app/messages/api/queue/insert-incoming-message.ts @@ -19,9 +19,7 @@ const insertIncomingMessageQueue = Queue( } const encryptionKey = customer.encryptionKey; - const message = await twilio(customer.accountSid, customer.authToken) - .messages.get(messageSid) - .fetch(); + const message = await twilio(customer.accountSid, customer.authToken).messages.get(messageSid).fetch(); await db.message.create({ data: { customerId, diff --git a/app/messages/api/queue/insert-messages.ts b/app/messages/api/queue/insert-messages.ts index 7afd029..47a19ed 100644 --- a/app/messages/api/queue/insert-messages.ts +++ b/app/messages/api/queue/insert-messages.ts @@ -9,28 +9,25 @@ type Payload = { messages: MessageInstance[]; }; -const insertMessagesQueue = Queue( - "api/queue/insert-messages", - async ({ messages, customerId }) => { - const customer = await db.customer.findFirst({ where: { id: customerId } }); - const encryptionKey = customer!.encryptionKey; +const insertMessagesQueue = Queue("api/queue/insert-messages", async ({ messages, customerId }) => { + const customer = await db.customer.findFirst({ where: { id: customerId } }); + const encryptionKey = customer!.encryptionKey; - const sms = messages - .map>((message) => ({ - customerId, - content: encrypt(message.body, encryptionKey), - from: message.from, - to: message.to, - status: translateStatus(message.status), - direction: translateDirection(message.direction), - twilioSid: message.sid, - sentAt: new Date(message.dateCreated), - })) - .sort((a, b) => a.sentAt.getTime() - b.sentAt.getTime()); + const sms = messages + .map>((message) => ({ + customerId, + content: encrypt(message.body, encryptionKey), + from: message.from, + to: message.to, + status: translateStatus(message.status), + direction: translateDirection(message.direction), + twilioSid: message.sid, + sentAt: new Date(message.dateCreated), + })) + .sort((a, b) => a.sentAt.getTime() - b.sentAt.getTime()); - await db.message.createMany({ data: sms }); - }, -); + await db.message.createMany({ data: sms }); +}); export default insertMessagesQueue; diff --git a/app/messages/api/queue/send-message.ts b/app/messages/api/queue/send-message.ts index 96cfe51..6a58da3 100644 --- a/app/messages/api/queue/send-message.ts +++ b/app/messages/api/queue/send-message.ts @@ -17,10 +17,7 @@ const sendMessageQueue = Queue( const phoneNumber = await db.phoneNumber.findFirst({ where: { customerId } }); try { - const message = await twilio( - customer!.accountSid!, - customer!.authToken!, - ).messages.create({ + const message = await twilio(customer!.accountSid!, customer!.authToken!).messages.create({ body: content, to, from: phoneNumber!.phoneNumber, diff --git a/app/messages/api/webhook/incoming-message.ts b/app/messages/api/webhook/incoming-message.ts index 9041469..221cb4e 100644 --- a/app/messages/api/webhook/incoming-message.ts +++ b/app/messages/api/webhook/incoming-message.ts @@ -57,12 +57,7 @@ export default async function incomingMessageHandler(req: BlitzApiRequest, res: } const url = `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/incoming-message`; - const isRequestValid = twilio.validateRequest( - customer.authToken, - twilioSignature, - url, - req.body, - ); + const isRequestValid = twilio.validateRequest(customer.authToken, twilioSignature, url, req.body); if (!isRequestValid) { const statusCode = 400; const apiError: ApiError = { diff --git a/app/messages/components/conversation.tsx b/app/messages/components/conversation.tsx index 7f22c93..70e22eb 100644 --- a/app/messages/components/conversation.tsx +++ b/app/messages/components/conversation.tsx @@ -28,8 +28,7 @@ export default function Conversation() { const isSameNext = message.from === nextMessage?.from; const isSamePrevious = message.from === previousMessage?.from; const differenceInMinutes = previousMessage - ? (new Date(message.sentAt).getTime() - - new Date(previousMessage.sentAt).getTime()) / + ? (new Date(message.sentAt).getTime() - new Date(previousMessage.sentAt).getTime()) / 1000 / 60 : 0; @@ -63,9 +62,7 @@ export default function Conversation() { {message.content} diff --git a/app/messages/components/conversations-list.tsx b/app/messages/components/conversations-list.tsx index 67872c4..d4b20ca 100644 --- a/app/messages/components/conversations-list.tsx +++ b/app/messages/components/conversations-list.tsx @@ -23,9 +23,7 @@ export default function ConversationsList() {
{recipient} -
- {new Date(lastMessage.sentAt).toLocaleString("fr-FR")} -
+
{new Date(lastMessage.sentAt).toLocaleString("fr-FR")}
{lastMessage.content}
diff --git a/app/messages/components/new-message-bottom-sheet.tsx b/app/messages/components/new-message-bottom-sheet.tsx index a48147e..024577b 100644 --- a/app/messages/components/new-message-bottom-sheet.tsx +++ b/app/messages/components/new-message-bottom-sheet.tsx @@ -41,9 +41,7 @@ export default function NewMessageBottomSheet() { { - router - .push(Routes.ConversationPage({ recipient })) - .then(() => setIsOpen(false)); + router.push(Routes.ConversationPage({ recipient })).then(() => setIsOpen(false)); }} /> diff --git a/app/messages/mutations/send-message.ts b/app/messages/mutations/send-message.ts index 66ecca7..1acbb2b 100644 --- a/app/messages/mutations/send-message.ts +++ b/app/messages/mutations/send-message.ts @@ -16,45 +16,39 @@ const Body = z.object({ to: z.string(), }); -export default resolver.pipe( - resolver.zod(Body), - resolver.authorize(), - async ({ content, to }, context) => { - const customer = await getCurrentCustomer(null, context); - try { - await twilio(customer!.accountSid!, customer!.authToken!) - .lookups.v1.phoneNumbers(to) - .fetch(); - } catch (error) { - logger.error(error); - return; - } +export default resolver.pipe(resolver.zod(Body), resolver.authorize(), async ({ content, to }, context) => { + const customer = await getCurrentCustomer(null, context); + try { + await twilio(customer!.accountSid!, customer!.authToken!).lookups.v1.phoneNumbers(to).fetch(); + } catch (error) { + logger.error(error); + return; + } - const customerId = customer!.id; - const customerPhoneNumber = await getCustomerPhoneNumber({ customerId }, context); + const customerId = customer!.id; + const customerPhoneNumber = await getCustomerPhoneNumber({ customerId }, context); - const message = await db.message.create({ - data: { - customerId, - to, - from: customerPhoneNumber!.phoneNumber, - direction: Direction.Outbound, - status: MessageStatus.Queued, - content: encrypt(content, customer!.encryptionKey), - sentAt: new Date(), - }, - }); + const message = await db.message.create({ + data: { + customerId, + to, + from: customerPhoneNumber!.phoneNumber, + direction: Direction.Outbound, + status: MessageStatus.Queued, + content: encrypt(content, customer!.encryptionKey), + sentAt: new Date(), + }, + }); - await sendMessageQueue.enqueue( - { - id: message.id, - customerId, - to, - content, - }, - { - id: message.id, - }, - ); - }, -); + await sendMessageQueue.enqueue( + { + id: message.id, + customerId, + to, + content, + }, + { + id: message.id, + }, + ); +}); diff --git a/app/messages/pages/messages/[recipient].tsx b/app/messages/pages/messages/[recipient].tsx index 5de12f2..ff2ab6a 100644 --- a/app/messages/pages/messages/[recipient].tsx +++ b/app/messages/pages/messages/[recipient].tsx @@ -2,11 +2,7 @@ import { Suspense } from "react"; import type { BlitzPage } from "blitz"; import { Routes, useRouter } from "blitz"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - faLongArrowLeft, - faInfoCircle, - faPhoneAlt as faPhone, -} from "@fortawesome/pro-regular-svg-icons"; +import { faLongArrowLeft, faInfoCircle, faPhoneAlt as faPhone } from "@fortawesome/pro-regular-svg-icons"; import Layout from "../../../core/layouts/layout"; import Conversation from "../../components/conversation"; diff --git a/app/messages/queries/get-conversation.ts b/app/messages/queries/get-conversation.ts index 74c6797..b4ccea3 100644 --- a/app/messages/queries/get-conversation.ts +++ b/app/messages/queries/get-conversation.ts @@ -9,23 +9,19 @@ const GetConversations = z.object({ recipient: z.string(), }); -export default resolver.pipe( - resolver.zod(GetConversations), - resolver.authorize(), - async ({ recipient }, context) => { - const customer = await getCurrentCustomer(null, context); - const conversation = await db.message.findMany({ - where: { - OR: [{ from: recipient }, { to: recipient }], - }, - orderBy: { sentAt: Prisma.SortOrder.asc }, - }); +export default resolver.pipe(resolver.zod(GetConversations), resolver.authorize(), async ({ recipient }, context) => { + const customer = await getCurrentCustomer(null, context); + const conversation = await db.message.findMany({ + where: { + OR: [{ from: recipient }, { to: recipient }], + }, + orderBy: { sentAt: Prisma.SortOrder.asc }, + }); - return conversation.map((message) => { - return { - ...message, - content: decrypt(message.content, customer!.encryptionKey), - }; - }); - }, -); + return conversation.map((message) => { + return { + ...message, + content: decrypt(message.content, customer!.encryptionKey), + }; + }); +}); diff --git a/app/onboarding/api/queue/set-twilio-webhooks.ts b/app/onboarding/api/queue/set-twilio-webhooks.ts index aac7ca4..44cfe57 100644 --- a/app/onboarding/api/queue/set-twilio-webhooks.ts +++ b/app/onboarding/api/queue/set-twilio-webhooks.ts @@ -7,37 +7,32 @@ type Payload = { customerId: string; }; -const setTwilioWebhooks = Queue( - "api/queue/set-twilio-webhooks", - async ({ customerId }) => { - const customer = await db.customer.findFirst({ where: { id: customerId } }); - const twimlApp = customer!.twimlAppSid - ? await twilio(customer!.accountSid!, customer!.authToken!) - .applications.get(customer!.twimlAppSid) - .fetch() - : await twilio(customer!.accountSid!, customer!.authToken!).applications.create({ - friendlyName: "Virtual Phone", - smsUrl: "https://phone.mokhtar.dev/api/webhook/incoming-message", - smsMethod: "POST", - voiceUrl: "https://phone.mokhtar.dev/api/webhook/incoming-call", - voiceMethod: "POST", - }); - const twimlAppSid = twimlApp.sid; - const phoneNumber = await db.phoneNumber.findFirst({ where: { customerId } }); +const setTwilioWebhooks = Queue("api/queue/set-twilio-webhooks", async ({ customerId }) => { + const customer = await db.customer.findFirst({ where: { id: customerId } }); + const twimlApp = customer!.twimlAppSid + ? await twilio(customer!.accountSid!, customer!.authToken!).applications.get(customer!.twimlAppSid).fetch() + : await twilio(customer!.accountSid!, customer!.authToken!).applications.create({ + friendlyName: "Virtual Phone", + smsUrl: "https://phone.mokhtar.dev/api/webhook/incoming-message", + smsMethod: "POST", + voiceUrl: "https://phone.mokhtar.dev/api/webhook/incoming-call", + voiceMethod: "POST", + }); + const twimlAppSid = twimlApp.sid; + const phoneNumber = await db.phoneNumber.findFirst({ where: { customerId } }); - await Promise.all([ - db.customer.update({ - where: { id: customerId }, - data: { twimlAppSid }, + await Promise.all([ + db.customer.update({ + where: { id: customerId }, + data: { twimlAppSid }, + }), + twilio(customer!.accountSid!, customer!.authToken!) + .incomingPhoneNumbers.get(phoneNumber!.phoneNumberSid) + .update({ + smsApplicationSid: twimlAppSid, + voiceApplicationSid: twimlAppSid, }), - twilio(customer!.accountSid!, customer!.authToken!) - .incomingPhoneNumbers.get(phoneNumber!.phoneNumberSid) - .update({ - smsApplicationSid: twimlAppSid, - voiceApplicationSid: twimlAppSid, - }), - ]); - }, -); + ]); +}); export default setTwilioWebhooks; diff --git a/app/pages/_app.tsx b/app/pages/_app.tsx index c250d2e..d3cda58 100644 --- a/app/pages/_app.tsx +++ b/app/pages/_app.tsx @@ -17,13 +17,8 @@ export default function App({ Component, pageProps }: AppProps) { const getLayout = Component.getLayout || ((page) => page); return ( - - - {getLayout()} - + + {getLayout()} ); } @@ -32,18 +27,8 @@ function RootErrorFallback({ error, resetErrorBoundary }: ErrorFallbackProps) { if (error instanceof AuthenticationError) { return ; } else if (error instanceof AuthorizationError) { - return ( - - ); + return ; } else { - return ( - - ); + return ; } } diff --git a/app/pages/index.tsx b/app/pages/index.tsx index 1e80ac7..ccc225b 100644 --- a/app/pages/index.tsx +++ b/app/pages/index.tsx @@ -138,9 +138,8 @@ const Home: BlitzPage = () => { body { padding: 0; margin: 0; - font-family: "Libre Franklin", -apple-system, BlinkMacSystemFont, Segoe UI, - Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, - sans-serif; + font-family: "Libre Franklin", -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, + Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; } * { diff --git a/app/phone-calls/api/queue/fetch-calls.ts b/app/phone-calls/api/queue/fetch-calls.ts index 651af9d..66d68ff 100644 --- a/app/phone-calls/api/queue/fetch-calls.ts +++ b/app/phone-calls/api/queue/fetch-calls.ts @@ -20,9 +20,7 @@ const fetchCallsQueue = Queue("api/queue/fetch-calls", async ({ custome to: phoneNumber!.phoneNumber, }), ]); - const calls = [...callsSent, ...callsReceived].sort( - (a, b) => a.dateCreated.getTime() - b.dateCreated.getTime(), - ); + const calls = [...callsSent, ...callsReceived].sort((a, b) => a.dateCreated.getTime() - b.dateCreated.getTime()); await insertCallsQueue.enqueue( { diff --git a/app/phone-calls/queries/get-phone-calls.ts b/app/phone-calls/queries/get-phone-calls.ts index 0a68db1..d1163d5 100644 --- a/app/phone-calls/queries/get-phone-calls.ts +++ b/app/phone-calls/queries/get-phone-calls.ts @@ -1,8 +1,7 @@ import { paginate, resolver } from "blitz"; import db, { Prisma, Customer } from "db"; -interface GetPhoneCallsInput - extends Pick { +interface GetPhoneCallsInput extends Pick { customerId: Customer["id"]; } diff --git a/app/settings/components/alert.tsx b/app/settings/components/alert.tsx index 3e9c80a..c517aa4 100644 --- a/app/settings/components/alert.tsx +++ b/app/settings/components/alert.tsx @@ -82,14 +82,8 @@ export default function Alert({ title, message, variant }: Props) {
{variantProperties.icon}
-

- {title} -

-
- {message} -
+

{title}

+
{message}
diff --git a/app/settings/components/danger-zone.tsx b/app/settings/components/danger-zone.tsx index 0799c76..8eef4aa 100644 --- a/app/settings/components/danger-zone.tsx +++ b/app/settings/components/danger-zone.tsx @@ -28,38 +28,28 @@ export default function DangerZone() {
-

- Once you delete your account, all of its data will be permanently deleted. -

+

Once you delete your account, all of its data will be permanently deleted.

-
- +
Delete my account

- Are you sure you want to delete your account? Your subscription will - be cancelled and your data permanently deleted. + Are you sure you want to delete your account? Your subscription will be cancelled and + your data permanently deleted.

- You are free to create a new account with the same email address if - you ever wish to come back. + You are free to create a new account with the same email address if you ever wish to + come back.

diff --git a/app/settings/components/modal.tsx b/app/settings/components/modal.tsx index 4183317..1ee48af 100644 --- a/app/settings/components/modal.tsx +++ b/app/settings/components/modal.tsx @@ -32,9 +32,7 @@ const Modal: FunctionComponent = ({ children, initialFocus, isOpen, onClo {/* This element is to trick the browser into centering the modal contents. */} - - ​ - + {
{errorMessage ? (
- +
) : null} {isSubmitSuccessful ? (
- +
) : null}
-