Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:Email Template > Invoice Email Template #332

Merged
merged 7 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions app/components/InvoiceEmail/DetailTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Column, Heading, Row, Section, Text } from "@react-email/components";

interface Detail {
id: number;
label: string;
value: string;
}

interface DetailTableProperties {
title: string;
text: string;
details: Detail[];
}

const DetailTable = ({ title, text, details }: DetailTableProperties) => {
return (
<Section className="my-6" style={{ borderTop: "1px solid #CBD5E1" }}>
<Heading className="my-4 font-semibold">{title}</Heading>
{text && <Text className="-mt-4">{text}</Text>}

<div
className="rounded-lg p-6 py-2"
style={{ backgroundColor: "#F6F8FB" }}
>
{details.map((detail) => (
<Row className="border-b last:border-none" key={detail.id}>
<div className="align-center flex justify-between">
<Column className="py-2 text-sm text-[#434343]">
{detail.label}
</Column>
<Column className="py-2 text-sm font-semibold text-[#0A0A0A]">
{detail.value}
</Column>
</div>
</Row>
))}
</div>
</Section>
);
};

export default DetailTable;
59 changes: 59 additions & 0 deletions app/components/InvoiceEmail/EmailFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Img, Link } from "@react-email/components";

export default function EmailFooter() {
return (
<div className="m-auto w-[4/5] justify-center bg-[#F3EFEF] px-[48px] py-[32px] leading-[normal] tracking-[normal]">
<div className="mx-auto flex flex-col items-start justify-start gap-7 text-left text-sm">
<div className="flex w-full items-center justify-center gap-[33px]">
<Link>
<Img src="/public/icons/x.svg" />
</Link>
<Link>
<Img src="/public/icons/instagram.svg" />
</Link>
<Link>
<Img src="/public/icons/tiktok.svg" />
</Link>
<Link>
<Img src="/public/icons/reddit.svg" />
</Link>
<Link>
<Img src="/public/icons/linkedin.svg" />
</Link>
</div>
<p className="text-[14px] text-[#5B5B5D]">
{`Thank you for choosing Boilerplate.com. Need help? `}
<Link
className="font-semibold text-black underline hover:no-underline"
href="#"
>
Contact our customer support
</Link>
</p>
<div className="h-0 w-full border-t border-dashed border-[#5B5B5D]"></div>
<p className="flex flex-col gap-3 text-[14px] text-[#5B5B5D]">
<span className="block">
You are receiving this email because you signed up at
Boilerplate.com. Want to change how you receive these emails?
</span>
<span>
You can
<Link
className="pl-1 font-semibold text-black underline hover:no-underline"
href="#"
>
Update your preference
</Link>
or
<Link
className="pl-1 font-semibold text-black underline hover:no-underline"
href="#"
>
Unsuscribe from this list.
</Link>
</span>
</p>
</div>
</div>
);
}
45 changes: 45 additions & 0 deletions app/components/InvoiceEmail/OrderSummaryTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Column, Heading, Row, Section } from "@react-email/components";

interface OrderDetail {
id: number;
label: string;
value: string;
amt: string;
}

interface OrderSummaryTableProperties {
title: string;
details: OrderDetail[];
}

const OrderSummaryTable = ({ title, details }: OrderSummaryTableProperties) => {
return (
<Section className="my-6" style={{ borderTop: "1px solid #CBD5E1" }}>
<div>
<Heading className="my-4 font-semibold">{title}</Heading>
</div>
<div
className="rounded-lg px-6 py-2"
style={{ backgroundColor: "#F6F8FB" }}
>
{details.map((detail) => (
<Row className="border-b last:border-none" key={detail.id}>
<div className="align-center flex justify-between">
<Column className="py-2 text-sm text-[#434343]">
{detail.label}
</Column>
<Column className="py-2 text-center text-sm">
{detail.value}
</Column>
<Column className="py-2 text-sm font-semibold text-[#0A0A0A]">
{detail.amt}
</Column>
</div>
</Row>
))}
</div>
</Section>
);
};

export default OrderSummaryTable;
167 changes: 167 additions & 0 deletions app/email/templates/invoice-email-temp/InvoiceEmail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import {
Body,
Button,
Container,
Head,
Heading,
Html,
Img,
Link,
Section,
Tailwind,
Text,
} from "@react-email/components";

import DetailTable from "~/components/InvoiceEmail/DetailTable";
import EmailFooter from "~/components/InvoiceEmail/EmailFooter";
import OrderSummaryTable from "~/components/InvoiceEmail/OrderSummaryTable";
import { invoiceDetails, orderSummary, paymentDetails } from "./data";

interface infoProperties {
phone: string;
email: string;
}

const InvoiceEmail = ({
phone = "-456-7890",
email = "[email protected]",
}: infoProperties) => {
return (
<>
<Html>
<Head>
<style>
{`
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap');

@media (min-width: 640px) {
.container-width {
max-width: 420px;
}
.show{
visibility: hidden;
}
}
@media (min-width: 768px) {
.container-width {
max-width: 792px;
}
.show{
display:none;
}
}

@media (min-width: 1024px) {
.container-width {
max-width: 792px;
}

}


@media (min-width: 768px){
.show{
display: block;
visibility: visible;
}
}

@media (max-width:640px){
.show{
visibility: hidden;
display:none;
}
}


`}
</style>
</Head>
<Tailwind>
<Body
className="container-width mx-auto"
style={{ fontFamily: "inter" }}
>
<Container>
<div className="bg-[#E1D6D666] p-4">
<Img
className="mx-auto"
src="/public/images/logo-text.svg"
alt="Logo"
/>
</div>

<div className="p-10">
<Section>
<Img
className="mx-auto"
src="/public/images/money-transfer-email.png"
alt="money-transfer-invoice"
/>

<Heading className="show py-8 text-center text-2xl font-semibold">
Invoice
</Heading>

<Text className="pt-4 font-semibold text-[#0A0A0A]">
Hi John Doe,
</Text>

<Text className="text-[#111111]">
We hope you are doing well. Thank you for your recent
purchase from Boilerplate. Please find your invoice attached
to this email.
</Text>
</Section>

<div>
<DetailTable
title="Invoice Details"
text=""
details={invoiceDetails}
/>
<OrderSummaryTable
title="Order Summary"
details={orderSummary}
/>
<DetailTable
title="Payment Details"
text="Please ensure to pay into this account within two days from today."
details={paymentDetails}
/>

<div className="py-6">
<Link>
<Button className="align-center mx-auto flex w-[142px] justify-center rounded-lg bg-[#F97316] px-[8px] py-[10px] font-bold text-[#FAF8F8]">
Pay Now
</Button>
</Link>
</div>
</div>

<Section>
<Text>Have any questions about your order?</Text>
<Text>
Give us a call at (+234){phone} or Email us at {email}
</Text>

<div>
<Text>
Regards, <br />
Boilerplate
</Text>
{/* <Text>Boilerplate</Text> */}
</div>
</Section>
</div>

<EmailFooter />
</Container>
</Body>
</Tailwind>
</Html>
</>
);
};

export default InvoiceEmail;
33 changes: 33 additions & 0 deletions app/email/templates/invoice-email-temp/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export interface Detail {
id: number;
label: string;
value: string;
}

export const invoiceDetails: Detail[] = [
{ id: 1, label: "Invoice Number", value: "#EJ78465" },
{ id: 2, label: "Date of Issue", value: "July 17, 2024" },
{ id: 3, label: "Due Date", value: "July 19, 2024" },
];

export const paymentDetails: Detail[] = [
{ id: 1, label: "Amount", value: "$352" },
{ id: 2, label: "Payment Method", value: "Bank" },
{ id: 3, label: "Bank Name", value: " United Bank of Africa" },
{ id: 4, label: "Account Number", value: "2108689490" },
{ id: 5, label: "Account Name", value: "John Doe" },
];

export interface OrderDetail {
id: number;
label: string;
value: string;
amt: string;
}

export const orderSummary: OrderDetail[] = [
{ id: 1, label: "Item", value: "5", amt: "$450.00" },
{ id: 2, label: "Item", value: "5", amt: "$50.00" },
{ id: 3, label: "VAT", value: "10%", amt: "$500.00" },
{ id: 4, label: "TOTAL", value: "100%", amt: "$500.00" },
];
16 changes: 4 additions & 12 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ import {
Outlet,
Scripts,
ScrollRestoration,
useLocation,
} from "@remix-run/react";
import type { ReactNode } from "react";

import FooterLight from "./components/ui/footerLight";
import Header from "./components/ui/header";
import { AdminSideNavBar } from "./components/SuperAdminSideBar/SuperAdminSideNavBar";
import styles from "./styles/global.css?url";

export const links: LinksFunction = () => [
Expand All @@ -20,9 +18,6 @@ export const links: LinksFunction = () => [
];

export function Layout({ children }: { children: ReactNode }) {
const location = useLocation();
const pagesWithNoFooter = ["/dashboard/password-settings"];
const showFooter = !pagesWithNoFooter.includes(location.pathname);
return (
<html lang="en">
<head>
Expand All @@ -32,12 +27,9 @@ export function Layout({ children }: { children: ReactNode }) {
<Links />
</head>
<body>
<div>
<main>
<Header />
{children}
{showFooter && <FooterLight />}
</main>
<div className="flex">
<AdminSideNavBar />
<main className="flex-1">{children}</main>,
<ScrollRestoration />
<Scripts />
</div>
Expand Down
Loading