Skip to content

Commit

Permalink
refactor: Use generated types from Supabase (#471)
Browse files Browse the repository at this point in the history
* Use generated types

* OK

* Fix migration
  • Loading branch information
amaury1093 authored Dec 12, 2023
1 parent ee11423 commit 04ee2a8
Show file tree
Hide file tree
Showing 23 changed files with 854 additions and 199 deletions.
10 changes: 3 additions & 7 deletions src/components/ApiUsage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Capacity, Loading, Spacer, Text } from "@geist-ui/react";
import { Loader } from "@geist-ui/react-icons";
import { format, parseISO } from "date-fns";
import React, { useEffect, useState } from "react";

import { sentryException } from "@/util/sentry";
Expand All @@ -9,6 +8,7 @@ import { getApiUsageClient } from "@/util/supabaseClient";
import { useUser } from "@/util/useUser";
import styles from "./ApiUsage.module.css";
import { Demo } from "./Demo";
import { formatDate } from "@/util/helpers";

export function ApiUsage(): React.ReactElement {
const { subscription, user, userFinishedLoading } = useUser();
Expand All @@ -18,7 +18,7 @@ export function ApiUsage(): React.ReactElement {
if (!user || !userFinishedLoading) {
return;
}
getApiUsageClient(user, subscription)
getApiUsageClient(subscription)
.then(setApiCalls)
.catch(sentryException);
}, [user, userFinishedLoading, subscription]);
Expand Down Expand Up @@ -62,14 +62,10 @@ export function ApiUsage(): React.ReactElement {
<Spacer />
<Demo
onVerified={() =>
getApiUsageClient(user, subscription).then(setApiCalls)
getApiUsageClient(subscription).then(setApiCalls)
}
/>
<Spacer />
</section>
);
}

function formatDate(d: string | Date): string {
return format(typeof d === "string" ? parseISO(d) : d, "do MMM yyyy");
}
35 changes: 19 additions & 16 deletions src/components/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import {
productName,
SAAS_10K_PRODUCT_ID,
} from "@/util/subs";
import { SupabaseProductWithPrice } from "@/util/supabaseClient";
import { useUser } from "@/util/useUser";
import { ApiUsage } from "./ApiUsage";
import styles from "./Dashboard.module.css";
import { ProductWithPrice } from "@/supabase/domain.types";
import { formatDate } from "@/util/helpers";

interface DashboardProps {
products: SupabaseProductWithPrice[];
products: ProductWithPrice[];
}

export function Dashboard({ products }: DashboardProps): React.ReactElement {
Expand All @@ -40,13 +41,27 @@ export function Dashboard({ products }: DashboardProps): React.ReactElement {
<Page>
<section className={styles.plan}>
<div>
<Spacer y={2} />
<Text h2>Hello{userDetails?.full_name || ""},</Text>
<Text p>
Thanks for using the Reacher{" "}
{productName(subscription?.prices?.products)}!
</Text>
<div className="flex">
<StripeMananageButton>Billing History</StripeMananageButton>
</div>
<div>
<Text className="text-right" p>
Active Subscription
</Text>
<Text className="text-right" h3>
{productName(subscription?.prices?.products)}
</Text>
{subscription?.cancel_at && (
<Text p small em className="text-right mt-0">
⚠️ Plan ends on{" "}
{formatDate(new Date(subscription.cancel_at))}
</Text>
)}
<div className="text-right">
{subscription ? (
<StripeMananageButton>
Manage Subscription
Expand All @@ -60,20 +75,8 @@ export function Dashboard({ products }: DashboardProps): React.ReactElement {
<strong>Upgrade Plan</strong>
</GLink>
)}
<Spacer />
<StripeMananageButton>
Billing History
</StripeMananageButton>
</div>
</div>
<div>
<Text className="text-right" p>
Active Subscription
</Text>
<Text className="text-right" h3>
{productName(subscription?.prices?.products)}
</Text>
</div>
</section>

<Spacer y={3} />
Expand Down
18 changes: 8 additions & 10 deletions src/components/ProductCard/Sub.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,17 @@ import { postData } from "@/util/helpers";
import { sentryException } from "@/util/sentry";
import { getStripe } from "@/util/stripeClient";
import { COMMERCIAL_LICENSE_PRODUCT_ID } from "@/util/subs";
import type {
SupabasePrice,
SupabaseProductWithPrice,
SupabaseSubscription,
} from "@/util/supabaseClient";
import type {} from "@/util/supabaseClient";
import { useUser } from "@/util/useUser";
import { Card } from "./Card";
import styles from "./Card.module.css";
import { Tables } from "@/supabase/database.types";
import { ProductWithPrice } from "@/supabase/domain.types";

export interface ProductCardProps {
currency: string;
product: SupabaseProductWithPrice;
subscription: SupabaseSubscription | null;
product: ProductWithPrice;
subscription: Tables<"subscriptions"> | null;
}

export function ProductCard({
Expand All @@ -37,7 +35,7 @@ export function ProductCard({
return <p>Error: No price found for product {product.id}.</p>;
}

const handleCheckout = async (price: SupabasePrice) => {
const handleCheckout = async (price: Tables<"prices">) => {
setPriceIdLoading(price.id);

if (!session) {
Expand Down Expand Up @@ -69,7 +67,7 @@ export function ProductCard({

const priceString = new Intl.NumberFormat("en-US", {
style: "currency",
currency: price.currency,
currency: price.currency || undefined,
minimumFractionDigits: 0,
}).format(price.unit_amount / 100);

Expand Down Expand Up @@ -155,7 +153,7 @@ export function ProductCard({
</span>
)
}
title={product.name}
title={product.name || "No Product Name"} // Latter should never happen
/>
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/SubGetStarted/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from "react";

import { COMMERCIAL_LICENSE_PRODUCT_ID } from "@/util/subs";
import { SupabaseSubscription } from "@/util/supabaseClient";
import { GetStartedLicense } from "./GetStartedLicense";
import { GetStartedSaas } from "./GetStartedSaas";
import { SubscriptionWithPrice } from "@/supabase/domain.types";

interface SubGetStartedProps {
subscription: SupabaseSubscription | null; // null means Free Trial
subscription: SubscriptionWithPrice | null; // null means Free Trial
}

export function SubGetStarted({
Expand Down
4 changes: 2 additions & 2 deletions src/pages/api/sendinblue/create-contact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { NextApiRequest, NextApiResponse } from "next";

import { sendinblueApi } from "@/util/sendinblue";
import { sentryException } from "@/util/sentry";
import type { SupabaseUser } from "@/util/supabaseClient";
import { getUser, supabaseAdmin } from "@/util/supabaseServer";
import { Tables } from "@/supabase/database.types";

const createContact = async (
req: NextApiRequest,
Expand Down Expand Up @@ -73,7 +73,7 @@ async function updateUserSendinblueContactId(
}

await supabaseAdmin
.from<SupabaseUser>("users")
.from<Tables<"users">>("users")
.update({
sendinblue_contact_id: body.id.toString(),
})
Expand Down
4 changes: 2 additions & 2 deletions src/pages/api/stripe/create-checkout-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { NextApiRequest, NextApiResponse } from "next";
import { getWebappURL } from "@/util/helpers";
import { sentryException } from "@/util/sentry";
import { stripe } from "@/util/stripeServer";
import { SupabasePrice } from "@/util/supabaseClient";
import { getActiveSubscription, getUser } from "@/util/supabaseServer";
import { createOrRetrieveCustomer } from "@/util/useDatabase";
import { Tables } from "@/supabase/database.types";

const createCheckoutSession = async (
req: NextApiRequest,
Expand All @@ -24,7 +24,7 @@ const createCheckoutSession = async (
quantity = 1,
metadata = {},
} = req.body as {
price: SupabasePrice;
price: Tables<"prices">;
quantity: number;
metadata: Record<string, string>;
};
Expand Down
20 changes: 5 additions & 15 deletions src/pages/api/v0/check_email.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { CheckEmailInput, CheckEmailOutput } from "@reacherhq/api";
import type { CheckEmailInput } from "@reacherhq/api";
import { NextApiRequest, NextApiResponse } from "next";
import { v4 } from "uuid";
import amqplib from "amqplib";
import dns from "dns/promises";

import { checkUserInDB, cors } from "@/util/api";
import { checkUserInDB, cors, removeSensitiveData } from "@/util/api";
import { updateSendinblue } from "@/util/sendinblue";
import { sentryException } from "@/util/sentry";
import { SupabaseCall } from "@/util/supabaseClient";
import { supabaseAdmin } from "@/util/supabaseServer";
import { Tables } from "@/supabase/database.types";

const TIMEOUT = 50000;
const MAX_PRIORITY = 5; // Higher is faster, 5 is max.
Expand Down Expand Up @@ -74,7 +74,7 @@ const POST = async (

// Add to supabase
const response = await supabaseAdmin
.from<SupabaseCall>("calls")
.from<Tables<"calls">>("calls")
.insert({
endpoint: "/v0/check_email",
user_id: user.id,
Expand Down Expand Up @@ -188,7 +188,7 @@ export default POST;

// getVerifMethod returns the verifMethod that is best used to verify the
// input's email address.
async function getVerifMethod(input: CheckEmailInput): Promise<string> {
export async function getVerifMethod(input: CheckEmailInput): Promise<string> {
try {
const domain = input.to_email.split("@")[1];
if (!domain) {
Expand Down Expand Up @@ -218,13 +218,3 @@ async function getVerifMethod(input: CheckEmailInput): Promise<string> {
return "Smtp";
}
}

// Remove sensitive data before storing to DB.
function removeSensitiveData(output: CheckEmailOutput): CheckEmailOutput {
const newOutput = { ...output };

// @ts-expect-error - We don't want to store the server name.
delete newOutput.debug?.server_name;

return newOutput;
}
10 changes: 4 additions & 6 deletions src/pages/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import React, { useEffect } from "react";

import { Dashboard, Nav } from "../components";
import { sentryException } from "@/util/sentry";
import {
getActiveProductsWithPrices,
SupabaseProductWithPrice,
} from "@/util/supabaseClient";
import { getActiveProductWithPrices } from "@/util/supabaseClient";
import { useUser } from "@/util/useUser";
import { ProductWithPrice } from "@/supabase/domain.types";

export const getStaticProps: GetStaticProps = async () => {
const products = await getActiveProductsWithPrices();
const products = await getActiveProductWithPrices();

return {
props: {
Expand All @@ -22,7 +20,7 @@ export const getStaticProps: GetStaticProps = async () => {
};

interface IndexProps {
products: SupabaseProductWithPrice[];
products: ProductWithPrice[];
}

export default function Index({ products }: IndexProps): React.ReactElement {
Expand Down
4 changes: 2 additions & 2 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { useState } from "react";
import { Nav } from "../components";
import { parseHashComponents, postData } from "@/util/helpers";
import { sentryException } from "@/util/sentry";
import { getActiveProductsWithPrices } from "@/util/supabaseClient";
import { getActiveProductWithPrices } from "@/util/supabaseClient";
import { useUser } from "@/util/useUser";

export const getStaticProps: GetStaticProps = async () => {
const products = await getActiveProductsWithPrices();
const products = await getActiveProductWithPrices();

return {
props: {
Expand Down
10 changes: 4 additions & 6 deletions src/pages/pricing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ import {
COMMERCIAL_LICENSE_PRODUCT_ID,
SAAS_10K_PRODUCT_ID,
} from "@/util/subs";
import {
getActiveProductsWithPrices,
SupabaseProductWithPrice,
} from "@/util/supabaseClient";
import { getActiveProductWithPrices } from "@/util/supabaseClient";
import { useUser } from "@/util/useUser";
import { ProductWithPrice } from "@/supabase/domain.types";

export const getStaticProps: GetStaticProps = async () => {
const products = await getActiveProductsWithPrices();
const products = await getActiveProductWithPrices();

return {
props: {
Expand All @@ -24,7 +22,7 @@ export const getStaticProps: GetStaticProps = async () => {
};

interface PricingProps {
products: SupabaseProductWithPrice[];
products: ProductWithPrice[];
}

export default function Pricing({
Expand Down
Loading

0 comments on commit 04ee2a8

Please sign in to comment.