Skip to content

Commit

Permalink
Email wip
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusab committed Nov 13, 2023
1 parent 0ec0f65 commit 58d7ed8
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 97 deletions.
40 changes: 39 additions & 1 deletion apps/dashboard/src/jobs/transactions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { client } from "@/trigger";
import { getTransactions } from "@midday/gocardless";
import { TriggerEvents, trigger, triggerBulk } from "@midday/notification";
import { Database } from "@midday/supabase/src/types";
import { eventTrigger } from "@trigger.dev/sdk";
import { Supabase, SupabaseManagement } from "@trigger.dev/supabase";
Expand Down Expand Up @@ -82,7 +83,7 @@ client.defineJob({
await dynamicSchedule.register(payload.record.id, {
type: "interval",
options: {
seconds: 10 * 60, // 10 minutes
seconds: 3600 * 4, // every 4h
},
});
},
Expand Down Expand Up @@ -139,6 +140,43 @@ client.defineJob({
.select();

if (transactionsData?.length && transactionsData.length > 0) {
// Send notification for each transaction
triggerBulk(
transactionsData.map((transaction) => ({
name: TriggerEvents.TransactionNewInApp,
payload: {
html: "TODO",
},
users: [
{
subscriberId: "",
teamId: "123",
email: "",
fullName: "Pontus Abrahamsson",
avatarUrl: "https://",
},
],
}))
);

// Send email with react-email-template
trigger({
name: TriggerEvents.TransactionNewEmail,
payload: {
subject: "New transactions",
html: "TODO",
},
users: [
{
subscriberId: "",
teamId: "123",
email: "",
fullName: "Pontus Abrahamsson",
avatarUrl: "https://",
},
],
});

revalidateTag(`transactions_${data?.team_id}`);
revalidateTag(`spending_${data?.team_id}`);
revalidateTag(`metrics_${data?.team_id}`);
Expand Down
2 changes: 1 addition & 1 deletion apps/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"scripts": {
"build": "next build",
"clean": "git clean -xdf .next .turbo node_modules",
"dev": "next dev",
"dev": "next dev -p 3000",
"lint": "next lint",
"format": "biome format --write .",
"start": "next start",
Expand Down
Binary file added apps/website/public/email/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion apps/website/src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ export function middleware(request: NextRequest) {
}

export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico|auth).*)"],
matcher: ["/((?!.*\\.|api|_next/static|_next/image|favicon.ico|auth\\/).*)"],
};
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dev": "turbo dev --parallel",
"start:dashboard": "turbo dev --filter=@midday/dashboard",
"dev:dashboard": "turbo dev --filter=@midday/dashboard",
"dev:website": "turbo dev --filter=@midday/website",
"dev:desktop": "turbo dev --filter=@midday/desktop",
"jobs:dashboard": "turbo jobs --filter=@midday/dashboard",
"format": "biome format --write .",
Expand Down
249 changes: 162 additions & 87 deletions packages/email/emails/transactions.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { cn } from "@midday/ui/utils";
import {
Body,
Button,
Column,
Container,
Font,
Head,
Heading,
Hr,
Expand All @@ -15,124 +17,197 @@ import {
Tailwind,
Text,
} from "@react-email/components";
import { format } from "date-fns";
import * as React from "react";

type Transaction = {
id: string;
date: string;
amount: number;
name: string;
currency: string;
};

interface TransactionsEmailEmailProps {
username?: string;
userImage?: string;
invitedByUsername?: string;
invitedByEmail?: string;
teamName?: string;
teamImage?: string;
inviteLink?: string;
inviteFromIp?: string;
inviteFromLocation?: string;
firstName: string;
transactions: Transaction[];
locale: string;
}

const baseUrl = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "";
const defaultTransactions = [
{
id: "1",
date: new Date().toISOString(),
amount: -1000,
currency: "USD",
name: "Spotify",
},
{
id: "2",
date: new Date().toISOString(),
amount: 1000,
currency: "USD",
name: "H23504959",
},
{
id: "3",
date: new Date().toISOString(),
amount: -1000,
currency: "USD",
name: "Webflow",
},
{
id: "4",
date: new Date().toISOString(),
amount: -1000,
currency: "USD",
name: "Netflix",
},
];

const baseUrl =
process.env.NODE_ENV === "production"
? "https://midday.ai"
: "http://localhost:3000/email";

const baseAppUrl =
process.env.NODE_ENV === "production"
? "https://app.midday.ai"
: "http://localhost:3001";

export const TransactionsEmail = ({
username = "zenorocha",
userImage = `${baseUrl}/static/vercel-user.png`,
invitedByUsername = "bukinoshita",
invitedByEmail = "bukinoshita@example.com",
teamName = "My Project",
teamImage = `${baseUrl}/static/vercel-team.png`,
inviteLink = "https://vercel.com/teams/invite/foo",
inviteFromIp = "204.13.186.218",
inviteFromLocation = "São Paulo, Brazil",
firstName = "Viktor",
transactions = defaultTransactions,
locale = "en",
}: TransactionsEmailEmailProps) => {
const previewText = `Join ${invitedByUsername} on Vercel`;
const previewText = `Hi ${firstName}, We found 5 transactions thats missing receipts. Feel free to attach them to ease your own or your accountants work for upcoming declerations.`;

return (
<Html>
<Head />
<Head>
<Font
fontFamily="Instrument Sans"
fallbackFontFamily="Helvetica"
webFont={{
url: "https://fonts.gstatic.com/s/instrumentsans/v1/pxiTypc9vsFDm051Uf6KVwgkfoSxQ0GsQv8ToedPibnr0She1ZuWi3hKpA.woff2",
format: "woff2",
}}
/>
<Font
fontFamily="Instrument Sans"
fallbackFontFamily="Helvetica"
webFont={{
url: "https://fonts.gstatic.com/s/instrumentsans/v1/pxiTypc9vsFDm051Uf6KVwgkfoSxQ0GsQv8ToedPibnr0She1ZuWi3hKpA.woff2",
format: "woff2",
}}
fontWeight={600}
/>
</Head>
<Preview>{previewText}</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans">
<Container className="border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] w-[465px]">
<Container className="border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] w-[560px]">
<Section className="mt-[32px]">
<Img
src={`${baseUrl}/static/vercel-logo.png`}
width="40"
height="37"
alt="Vercel"
src={`${baseUrl}/logo.png`}
width="45"
height="45"
alt="Midday"
className="my-0 mx-auto"
/>
</Section>
<Heading className="text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0">
Join <strong>{teamName}</strong> on <strong>Vercel</strong>
<Heading className="text-black text-[21px] font-normal text-center p-0 my-[30px] mx-0">
You have <span className="font-medium">5 transactions</span> thats
missing <br />
receipts.
</Heading>
<Text className="text-black text-[14px] leading-[24px]">
Hello {username},
</Text>
<Text className="text-black text-[14px] leading-[24px]">
<strong>bukinoshita</strong> (
<Link
href={`mailto:${invitedByEmail}`}
className="text-blue-600 no-underline"
>
{invitedByEmail}
</Link>
) has invited you to the <strong>{teamName}</strong> team on{" "}
<strong>Vercel</strong>.
Hi {firstName}, We found{" "}
<span className="font-medium">5 transactions</span> thats missing
receipts. Feel free to attach them to ease your own or your
accountants work for upcoming declerations.
</Text>
<Section>
<Row>
<Column align="right">
<Img
className="rounded-full"
src={userImage}
width="64"
height="64"
/>
</Column>
<Column align="center">
<Img
src={`${baseUrl}/static/vercel-arrow.png`}
width="12"
height="9"
alt="invited you to"
/>
</Column>
<Column align="left">
<Img
className="rounded-full"
src={teamImage}
width="64"
height="64"
/>
</Column>
</Row>
</Section>

<table style={{ width: "100%" }}>
<thead>
<tr style={{ borderBottom: "1px solid black" }}>
<th align="left">
<Text className="text-[14px] font-medium m-0 p-0">
Date
</Text>
</th>
<th align="left" style={{ width: "50%" }}>
<Text className="text-[14px] font-medium m-0 p-0">
To/From
</Text>
</th>
<th align="left">
<Text className="text-[14px] font-medium m-0 p-0">
Amount
</Text>
</th>
</tr>
</thead>

<tbody>
{transactions.map((transaction) => (
<tr key={transaction.id}>
<td align="left">
<Text className="text-[14px] m-0 p-0 mt-1 pb-1">
{format(new Date(transaction.date), "MMM d")}
</Text>
</td>
<td align="left" style={{ width: "50%" }}>
<Link
href={`${baseAppUrl}/transactions?id=${transaction.id}`}
className={cn(
"text-black",
transaction.amount > 0 && "text-[#00C969]"
)}
>
<Text className="text-[14px] m-0 p-0 mt-1 pb-1">
{transaction.name}
</Text>
</Link>
</td>
<td align="left">
<Text
className={cn(
"text-[14px] m-0 p-0 mt-1 pb-1",
transaction.amount > 0 && "text-[#00C969]"
)}
>
{Intl.NumberFormat(locale, {
style: "currency",
currency: transaction.currency,
}).format(transaction.amount)}
</Text>
</td>
</tr>
))}
</tbody>
</table>

<Section className="text-center mt-[32px] mb-[32px]">
<Button
pX={20}
pY={12}
className="bg-[#000000] rounded text-white text-[12px] font-semibold no-underline text-center"
href={inviteLink}
className="bg-[#000000] rounded-xl text-white text-[12px] font-semibold no-underline text-center"
href={`${baseAppUrl}/transactions?from_id=${
transactions.at(0).id
}`}
>
Join the team
View transactions
</Button>
</Section>
<Text className="text-black text-[14px] leading-[24px]">
or copy and paste this URL into your browser:{" "}
<Link href={inviteLink} className="text-blue-600 no-underline">
{inviteLink}
</Link>
</Text>
<Hr className="border border-solid border-[#eaeaea] my-[26px] mx-0 w-full" />
<Text className="text-[#666666] text-[12px] leading-[24px]">
This invitation was intended for{" "}
<span className="text-black">{username} </span>.This invite was
sent from <span className="text-black">{inviteFromIp}</span>{" "}
located in{" "}
<span className="text-black">{inviteFromLocation}</span>. If you
were not expecting this invitation, you can ignore this email. If
you are concerned about your account's safety, please reply to
this email to get in touch with us.
Nam imperdiet congue volutpat. Nulla quis facilisis lacus. Vivamus
convallis sit amet lectus eget tincidunt. Vestibulum vehicula
rutrum nisl, sed faucibus neque. Donec lacus mi, rhoncus at dictum
eget, pulvinar at metus. Donec cursus tellus erat, a hendrerit
elit rutrum ut. Fusce quis tristique ligula. Etiam sit amet enim
vitae mauris auctor blandit id et nibh.
</Text>
</Container>
</Body>
Expand Down
3 changes: 2 additions & 1 deletion packages/email/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
"lint": "biome check .",
"format": "biome format --write .",
"check:types": "tsc --noEmit",
"dev": "email dev -p 3002",
"dev": "email dev -p 3003",
"export": "email export"
},
"dependencies": {
"@react-email/components": "0.0.6",
"date-fns": "^2.30.0",
"react-email": "1.9.3"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit 58d7ed8

Please sign in to comment.