feature - full font management
This commit is contained in:
parent
0cd8f39a40
commit
574e072ae5
|
@ -24,7 +24,7 @@ export default async function BlogsPage() {
|
||||||
subtitle={
|
subtitle={
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
<h2 className="text-base-content font-bold text-2xl lg:text-3xl text-center max-w-5xl mx-auto px-6">
|
<h2 className="text-base-content text-2xl font-medium text-center max-w-5xl mx-auto px-6">
|
||||||
Join us for the journey as we make great food. Learn and grow
|
Join us for the journey as we make great food. Learn and grow
|
||||||
together
|
together
|
||||||
</h2>
|
</h2>
|
||||||
|
|
|
@ -2,13 +2,24 @@ import Footer from "@/components/Footer";
|
||||||
import Background from "@/components/Utilities/Background";
|
import Background from "@/components/Utilities/Background";
|
||||||
import Spacer from "@/components/Utilities/Spacer";
|
import Spacer from "@/components/Utilities/Spacer";
|
||||||
import FormLeftDescriptionRightContactUs from "@/sections/ContactUs/FormLeftDescriptionRightContactUs";
|
import FormLeftDescriptionRightContactUs from "@/sections/ContactUs/FormLeftDescriptionRightContactUs";
|
||||||
|
import PageHeader from "@/sections/PageHeader";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
const page = () => {
|
const page = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full w-full bg-base-100 ">
|
<div className="flex flex-col h-full w-full bg-base-100 ">
|
||||||
<Background>
|
<Background>
|
||||||
<Spacer className="pt-28" />
|
<PageHeader
|
||||||
|
title="Contact Us"
|
||||||
|
subtitle={
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
<h2 className="text-base-content text-2xl font-medium content text-center max-w-6xl mx-auto px-6">
|
||||||
|
We'd love to talk about how we can help you.
|
||||||
|
</h2>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<FormLeftDescriptionRightContactUs />
|
<FormLeftDescriptionRightContactUs />
|
||||||
<Spacer className="mt-auto" />
|
<Spacer className="mt-auto" />
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|
|
@ -42,7 +42,7 @@ export default function PricingPage() {
|
||||||
subtitle={
|
subtitle={
|
||||||
<>
|
<>
|
||||||
{" "}
|
{" "}
|
||||||
<h2 className="text-base-content content text-center max-w-6xl mx-auto px-6">
|
<h2 className="text-base-content text-2xl font-medium content text-center max-w-6xl mx-auto px-6">
|
||||||
Are you ready for fresh South West produce to be delivered to
|
Are you ready for fresh South West produce to be delivered to
|
||||||
your door?
|
your door?
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -158,8 +158,8 @@ function PriceCard({
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col mx-auto mt-auto">
|
<div className="flex flex-col mx-auto mt-auto">
|
||||||
{!loading && (
|
{!loading && (
|
||||||
<div className="flex flex-row mx-auto gap-x-4 justify-center items-center mb-2">
|
<div className="flex flex-row mx-auto gap-x-2 justify-center items-center mb-2">
|
||||||
<h1 className="text-base-content ">
|
<h1 className="text-base-content text-4xl font-bold">
|
||||||
$
|
$
|
||||||
{isAnnual
|
{isAnnual
|
||||||
? (product?.yearlyPrice?.unit_amount ?? 0) / 100
|
? (product?.yearlyPrice?.unit_amount ?? 0) / 100
|
||||||
|
@ -177,7 +177,7 @@ function PriceCard({
|
||||||
isAnnual ? product.yearlyPrice : product.monthlyPrice
|
isAnnual ? product.yearlyPrice : product.monthlyPrice
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
className=" mx-auto flex text-sm font-semibold py-2 px-20 m-2 bg-gradient-to-r from-primary to-secondary rounded-full mb-4 cursor-pointer group-hover:animate-bounce"
|
className="btn btn-primary rounded-full bg-gradient-to-r from-primary to-secondary"
|
||||||
>
|
>
|
||||||
Try it!
|
Try it!
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -4,26 +4,6 @@
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
:root {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
--foreground-rgb: 0, 0, 0;
|
font-family: var(--heading-font);
|
||||||
--background-start-rgb: 214, 219, 220;
|
}
|
||||||
--background-end-rgb: 255, 255, 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--foreground-rgb: 255, 255, 255;
|
|
||||||
--background-start-rgb: 0, 0, 0;
|
|
||||||
--background-end-rgb: 0, 0, 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
color: rgb(var(--foreground-rgb));
|
|
||||||
background: linear-gradient(
|
|
||||||
to bottom,
|
|
||||||
transparent,
|
|
||||||
rgb(var(--background-end-rgb))
|
|
||||||
)
|
|
||||||
rgb(var(--background-start-rgb));
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import "@/styles/style.css";
|
import "../app/globals.css";
|
||||||
import { Arimo, Raleway } from "next/font/google";
|
import { Arimo, Raleway } from "next/font/google";
|
||||||
import { ToastContainer, toast } from "react-toastify";
|
import { ToastContainer, toast } from "react-toastify";
|
||||||
import "react-toastify/dist/ReactToastify.css";
|
import "react-toastify/dist/ReactToastify.css";
|
||||||
|
@ -11,7 +11,7 @@ import { GTagProvider, PHProvider, ThemeProvider } from "./providers";
|
||||||
import PrelineScript from "@/components/Utilities/PrelineScript";
|
import PrelineScript from "@/components/Utilities/PrelineScript";
|
||||||
|
|
||||||
const raleway = Raleway({
|
const raleway = Raleway({
|
||||||
variable: "--display-font",
|
variable: "--heading-font",
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -33,7 +33,11 @@ export default async function RootLayout({
|
||||||
const isUserLoggedIn = await isAuthenticated(cookies());
|
const isUserLoggedIn = await isAuthenticated(cookies());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="en" className="h-full" suppressHydrationWarning>
|
<html
|
||||||
|
lang="en"
|
||||||
|
className={`h-full ${raleway.variable} ${arimo.variable}`}
|
||||||
|
suppressHydrationWarning
|
||||||
|
>
|
||||||
<PHProvider>
|
<PHProvider>
|
||||||
<GTagProvider />
|
<GTagProvider />
|
||||||
<body className={`${arimo.className} bg-base-100 flex`}>
|
<body className={`${arimo.className} bg-base-100 flex`}>
|
||||||
|
|
|
@ -30,7 +30,9 @@ function BlogCard({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full h-2/5 ">
|
<div className="w-full h-2/5 ">
|
||||||
<h1 className="pt-4 pb-2 xl:pt-8 text-base-content ">{title}</h1>
|
<h1 className="pt-4 pb-2 xl:pt-8 text-base-content text-xl font-bold ">
|
||||||
|
{title}
|
||||||
|
</h1>
|
||||||
<p className="text-base-content ">{subtitle}</p>
|
<p className="text-base-content ">{subtitle}</p>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
import { ModalStatus } from "@/types";
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
interface ButtonProps {
|
|
||||||
status: ModalStatus;
|
|
||||||
text: string;
|
|
||||||
}
|
|
||||||
export const Button = ({ status, text }: ButtonProps) => {
|
|
||||||
const className = (() => {
|
|
||||||
switch (status) {
|
|
||||||
case ModalStatus.Loading:
|
|
||||||
return "btn text-primary-base-content bg-base-100 hover:bg-base-100 shadow disabled:bg-base-content disabled:shadow-none";
|
|
||||||
|
|
||||||
case ModalStatus.Success:
|
|
||||||
return "btn text-primary-base-content bg-base-100 hover:bg-base-100 shadow disabled:bg-base-content disabled:shadow-none";
|
|
||||||
|
|
||||||
case ModalStatus.Default:
|
|
||||||
return "btn text-primary-base-content bg-base-100 hover:bg-base-100 shadow";
|
|
||||||
|
|
||||||
default:
|
|
||||||
return "btn text-primary-base-content bg-base-100 hover:bg-base-100 shadow";
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className={className}
|
|
||||||
disabled={
|
|
||||||
status === ModalStatus.Success || status === ModalStatus.Loading
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{status === ModalStatus.Loading ? (
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
fill="none"
|
|
||||||
className="animate-spin -ml-1 mr-3 h-5 w-5 bg-base-content"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="10"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="4"
|
|
||||||
className="opacity-25"
|
|
||||||
></circle>
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
||||||
className="opacity-75"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{text}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Button;
|
|
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Icon from "./icon";
|
import Icon from "./Icon";
|
||||||
|
|
||||||
function Footer() {
|
function Footer() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Navigation from "./Navigation";
|
import Navigation from "./Navigation";
|
||||||
import ModalSignUp from "@/sections/ModalSignUp/ModalSignUp";
|
import ModalSignUp from "@/components/Modals/ModalSignUp";
|
||||||
import ModalSignIn from "@/sections/ModalSignIn/ModalSignIn";
|
import ModalSignIn from "@/components/Modals/ModalSignIn";
|
||||||
import { logout } from "@/app/(auth)/actions";
|
import { logout } from "@/app/(auth)/actions";
|
||||||
import { getAuthCookie } from "@/app/(auth)/actions";
|
import { getAuthCookie } from "@/app/(auth)/actions";
|
||||||
import { SourceModal } from "@/types";
|
import { SourceModal } from "@/types";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Icon from "./icon";
|
import Icon from "./Icon";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
interface LogoProps {
|
interface LogoProps {
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
const Modal = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{/* You can open the modal using document.getElementById('ID').showModal() method */}
|
|
||||||
<button
|
|
||||||
className="btn"
|
|
||||||
onClick={() => document.getElementById("my_modal_4").showModal()}
|
|
||||||
>
|
|
||||||
open modal
|
|
||||||
</button>
|
|
||||||
<dialog id="my_modal_4" className="modal">
|
|
||||||
<div className="modal-box w-11/12 max-w-5xl">
|
|
||||||
<h3 className="font-bold text-lg">Hello!</h3>
|
|
||||||
<p className="py-4">Click the button below to close</p>
|
|
||||||
<div className="modal-action">
|
|
||||||
<form method="dialog">
|
|
||||||
{/* if there is a button, it will close the modal */}
|
|
||||||
<button className="btn">Close</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</dialog>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Modal;
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Icon from "@/components/icon";
|
import Icon from "@/components/Icon";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
import colors from "@/utils/colors";
|
import colors from "@/utils/colors";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
@ -7,8 +7,6 @@ import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import { signInValidationSchema } from "@/utils/form";
|
import { signInValidationSchema } from "@/utils/form";
|
||||||
|
|
||||||
function ModalSignIn() {
|
function ModalSignIn() {
|
||||||
const { theme } = useTheme();
|
|
||||||
const color = colors[theme ?? "light"]["base-content"];
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
|
@ -19,23 +17,27 @@ function ModalSignIn() {
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<input type="checkbox" id="sign-in-modal" className="modal-toggle" />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="sign-in-modal"
|
||||||
|
className="modal-toggle"
|
||||||
|
onClick={() => {
|
||||||
|
reset();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<label htmlFor="sign-in-modal" className="modal cursor-pointer">
|
<label htmlFor="sign-in-modal" className="modal cursor-pointer">
|
||||||
<label className="modal-box relative bg-base-100 max-w-full md:max-w-[550px] py-4 px-3 md:p-6">
|
<label className="modal-box relative bg-base-100 max-w-full md:max-w-[550px] py-4 px-3 md:p-6">
|
||||||
<div className="flex justify-end pb-2 select-none">
|
<div className="flex justify-end pb-2 select-none">
|
||||||
<label
|
<label
|
||||||
htmlFor="sign-in-modal"
|
htmlFor="sign-in-modal"
|
||||||
className="cursor-pointer"
|
className="cursor-pointer text-base-content"
|
||||||
onClick={() => {
|
|
||||||
reset();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Icon name="Dismiss20Filled" size="medium" color={color} />
|
<Icon name="Dismiss20Filled" size="medium" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
className="w-[100%] bg-gradient-to-r from-primary to-secondary px-6 pt-2 mt-3 pb-6 rounded-lg"
|
className="w-[100%] bg-gradient-to-r from-primary to-secondary px-6 pt-2 mt-3 pb-6 rounded-lg text-primary-content"
|
||||||
data-aos="fade-up"
|
data-aos="fade-up"
|
||||||
>
|
>
|
||||||
<h3 className="pb-1 text-3xl font-bold md:text-3xl pt-6">
|
<h3 className="pb-1 text-3xl font-bold md:text-3xl pt-6">
|
|
@ -1,10 +1,5 @@
|
||||||
"use client";
|
import React from "react";
|
||||||
// TODO: Needs a complete rework to use the DaisyUI component
|
import Icon from "@/components/Icon";
|
||||||
|
|
||||||
import React, { useRef, useState } from "react";
|
|
||||||
import { ModalStatus } from "@/types";
|
|
||||||
import { FormRefMethods } from "../ModalSignIn/ModalSignInForm";
|
|
||||||
import Icon from "@/components/icon";
|
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import { signUpValidationSchema } from "@/utils/form";
|
import { signUpValidationSchema } from "@/utils/form";
|
||||||
|
@ -26,14 +21,11 @@ function ModalSignUp() {
|
||||||
id="sign-up-modal"
|
id="sign-up-modal"
|
||||||
className="modal-toggle"
|
className="modal-toggle"
|
||||||
name=""
|
name=""
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="sign-up-modal"
|
|
||||||
className="modal cursor-pointer"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
reset();
|
reset();
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
|
<label htmlFor="sign-up-modal" className="modal cursor-pointer">
|
||||||
<label className="modal-box relative max-w-full md:max-w-[550px] py-4 px-3 md:p-6">
|
<label className="modal-box relative max-w-full md:max-w-[550px] py-4 px-3 md:p-6">
|
||||||
<div className="flex justify-end pb-2 select-none">
|
<div className="flex justify-end pb-2 select-none">
|
||||||
<label
|
<label
|
||||||
|
@ -48,7 +40,7 @@ function ModalSignUp() {
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-grow flex-col h-[30rem] lg:h-full overflow-y-scroll">
|
<div className="flex flex-grow flex-col h-[30rem] lg:h-full overflow-y-scroll">
|
||||||
<div
|
<div
|
||||||
className="w-[100%] bg-gradient-to-r from-primary to-secondary px-6 mt-3 pb-6 rounded-lg"
|
className="w-[100%] bg-gradient-to-r from-primary to-secondary px-6 mt-3 pb-6 rounded-lg text-primary-content"
|
||||||
data-aos="fade-up"
|
data-aos="fade-up"
|
||||||
>
|
>
|
||||||
<h3 className="pb-1 text-3xl font-bold md:text-3xl pt-6">
|
<h3 className="pb-1 text-3xl font-bold md:text-3xl pt-6">
|
|
@ -31,7 +31,7 @@ function Navigation({ isUserLoggedIn }: { isUserLoggedIn: boolean }) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-none hidden lg:block">
|
<div className="flex-none hidden lg:block">
|
||||||
<ul className="menu menu-horizontal items-center text-base-content">
|
<ul className="menu menu-horizontal items-center text-base-content font-medium">
|
||||||
{/* Site branding */}
|
{/* Site branding */}
|
||||||
<div className="shrink-0 mr-4">
|
<div className="shrink-0 mr-4">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
|
|
|
@ -4,12 +4,11 @@ import {
|
||||||
createManagementSubscriptionSession,
|
createManagementSubscriptionSession,
|
||||||
getSubscriptions,
|
getSubscriptions,
|
||||||
} from "@/app/(auth)/actions";
|
} from "@/app/(auth)/actions";
|
||||||
import { ModalStatus, Subscription, User } from "@/types";
|
import { Subscription, User } from "@/types";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import Button from "@/components/Button";
|
|
||||||
import { useQRCode } from "next-qrcode";
|
import { useQRCode } from "next-qrcode";
|
||||||
|
|
||||||
interface ManageSubscriptionProps {
|
interface ManageSubscriptionProps {
|
||||||
|
@ -69,9 +68,7 @@ function AccountContent({ user }: ManageSubscriptionProps) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return loading ? (
|
return loading ? (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col"></div>
|
||||||
<Button status={ModalStatus.Loading} text="Loading..." />
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
{/* //TODO: Create Application Component */}
|
{/* //TODO: Create Application Component */}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import Image from "next/image";
|
||||||
function BlogContent({ post }: { post: any }) {
|
function BlogContent({ post }: { post: any }) {
|
||||||
return (
|
return (
|
||||||
<div className="bg-base-200 mx-4 lg:mx-0 px-8 py-12 rounded-lg">
|
<div className="bg-base-200 mx-4 lg:mx-0 px-8 py-12 rounded-lg">
|
||||||
<h1 className="prose text-4xl font-bold text-base-content">
|
<h1 className="font-heading text-4xl font-bold text-base-content">
|
||||||
{post.title}
|
{post.title}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|
|
@ -30,14 +30,6 @@ const FormLeftDescriptionRightContactUs = () => {
|
||||||
{/* Contact Us */}
|
{/* Contact Us */}
|
||||||
<div className="max-w-[85rem] px-4 sm:px-6 lg:px-8 mx-auto pb-10">
|
<div className="max-w-[85rem] px-4 sm:px-6 lg:px-8 mx-auto pb-10">
|
||||||
<div className="max-w-2xl lg:max-w-5xl mx-auto">
|
<div className="max-w-2xl lg:max-w-5xl mx-auto">
|
||||||
<div className="text-center">
|
|
||||||
<h1 className="font-bold text-base-content sm:text-4xl ">
|
|
||||||
Contact us
|
|
||||||
</h1>
|
|
||||||
<p className="mt-1 text-base-content ">
|
|
||||||
We'd love to talk about how we can help you.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="mt-12 grid items-start lg:grid-cols-2 gap-6 lg:gap-16">
|
<div className="mt-12 grid items-start lg:grid-cols-2 gap-6 lg:gap-16">
|
||||||
{/* Card */}
|
{/* Card */}
|
||||||
<div className="flex flex-col rounded-xl p-4 sm:p-6 lg:p-8 bg-base-100 min-h-[20rem]">
|
<div className="flex flex-col rounded-xl p-4 sm:p-6 lg:p-8 bg-base-100 min-h-[20rem]">
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
import Icon from "@/components/icon";
|
import Icon from "@/components/Icon";
|
||||||
import colors, { hexToRgb } from "@/utils/colors";
|
import colors, { hexToRgb } from "@/utils/colors";
|
||||||
import Footer from "@/components/Footer";
|
import Footer from "@/components/Footer";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
|
@ -38,7 +38,7 @@ const WaitingListWithImageHero = () => {
|
||||||
>
|
>
|
||||||
<div className="h-screen w-full bg-clip flex items-center justify-center">
|
<div className="h-screen w-full bg-clip flex items-center justify-center">
|
||||||
<div className="text-center py-8 px-4 sm:px-6 lg:px-8">
|
<div className="text-center py-8 px-4 sm:px-6 lg:px-8">
|
||||||
<h1 className="text-3xl text-base-content sm:text-4xl whitespace-nowrap flex flex-row justify-center pb-6 gap-x-3">
|
<h1 className="font-semibold text-3xl sm:text-6xl text-base-content font-heading whitespace-nowrap flex flex-row justify-center pb-6 gap-x-3">
|
||||||
<Icon name="LeafThree24Filled" size="xlarge" />
|
<Icon name="LeafThree24Filled" size="xlarge" />
|
||||||
Bethel Farms
|
Bethel Farms
|
||||||
</h1>
|
</h1>
|
||||||
|
@ -186,7 +186,7 @@ const WaitingListWithImageHero = () => {
|
||||||
</form>
|
</form>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<h2 className="text-2xl text-base-content sm:text-4xl">
|
<h2 className="sm:text-3xl font-body text-base-content">
|
||||||
You are on our waiting list. We will be in touch!
|
You are on our waiting list. We will be in touch!
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import ModalLearnMore from "./ModalLearnMore/ModalLearnMore";
|
|
||||||
import { SourceModal } from "@/types";
|
|
||||||
import { Raleway } from "next/font/google";
|
|
||||||
|
|
||||||
const raleway = Raleway({
|
|
||||||
variable: "--display-font",
|
|
||||||
subsets: ["latin"],
|
|
||||||
});
|
|
||||||
|
|
||||||
function HeroHome() {
|
|
||||||
const bookDemoOnClick = () => {
|
|
||||||
const signUpModal = document.getElementById("sign-up-modal");
|
|
||||||
if (!signUpModal) return;
|
|
||||||
signUpModal.setAttribute("name", SourceModal.BookDemo);
|
|
||||||
signUpModal.removeAttribute("price_id");
|
|
||||||
signUpModal.click();
|
|
||||||
};
|
|
||||||
|
|
||||||
const learnMoreOnClick = () => {
|
|
||||||
const learnMoreModal = document.getElementById("learn-more-modal");
|
|
||||||
if (!learnMoreModal) return;
|
|
||||||
learnMoreModal.click();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section>
|
|
||||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 relative">
|
|
||||||
{/* Hero content */}
|
|
||||||
<div className="relative pt-[12rem] pb-10 md:pt-40 md:pb-16">
|
|
||||||
{/* Section header */}
|
|
||||||
<div className="max-w-3xl mx-auto text-center pb-12 md:pb-10">
|
|
||||||
<h1
|
|
||||||
className={`${raleway.className} text-black font-raleway text-3xl leading-10 lg:py-12 tracking-[-1px] select-none w-[fit-content] md:leading-[6rem] m-auto mb-4 lg:mb-0 md:text-[5.5rem]`}
|
|
||||||
data-aos="fade-up"
|
|
||||||
>
|
|
||||||
Your Offline Digital Forms Simplified.
|
|
||||||
</h1>
|
|
||||||
<p
|
|
||||||
className="text-lg font-semibold pb-12 mb-8 md:text-4xl text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary w-[fit-content] mx-auto"
|
|
||||||
data-aos="fade-up"
|
|
||||||
data-aos-delay="200"
|
|
||||||
>
|
|
||||||
Sign365
|
|
||||||
</p>
|
|
||||||
<div className="max-w-xs mx-auto mt-[8rem] sm:max-w-none sm:flex sm:justify-center md:mt-auto">
|
|
||||||
<div data-aos="fade-up" data-aos-delay="400">
|
|
||||||
<button
|
|
||||||
onClick={bookDemoOnClick}
|
|
||||||
className="btn text-base capitalize rounded bg-base-content bg-secondary hover:bg-pink-700 w-full mb-4 sm:w-auto sm:mb-0"
|
|
||||||
>
|
|
||||||
Book Demo
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div data-aos="fade-up" data-aos-delay="600">
|
|
||||||
<button
|
|
||||||
onClick={learnMoreOnClick}
|
|
||||||
className="btn text-base capitalize rounded bg-base-content bg-gray-825 hover:bg-gray-650 w-full sm:w-auto sm:ml-4"
|
|
||||||
>
|
|
||||||
Learn more
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ModalLearnMore />
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default HeroHome;
|
|
|
@ -1,63 +0,0 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import SuccessModal from "../../sections/SuccessModal";
|
|
||||||
import LoadingModal from "../../sections/LoadingModal";
|
|
||||||
import xButton from "@/images/icon-x.svg";
|
|
||||||
import ModalLearnMoreForm from "../../sections/ModalLearnMore/ModalLearnMoreForm";
|
|
||||||
import Image from "next/image";
|
|
||||||
import { ModalStatus } from "@/types";
|
|
||||||
|
|
||||||
function ModalLearnMore() {
|
|
||||||
const [status, setStatus] = useState<ModalStatus>(ModalStatus.Default);
|
|
||||||
const whenModalOpens = () =>
|
|
||||||
setTimeout(() => setStatus(ModalStatus.Default), 500);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
id="learn-more-modal"
|
|
||||||
className="modal-toggle"
|
|
||||||
onChange={whenModalOpens}
|
|
||||||
/>
|
|
||||||
<label htmlFor="learn-more-modal" className="modal cursor-pointer">
|
|
||||||
<label className="modal-box relative bg-gray-850 max-w-full md:max-w-[550px] py-4 px-3 md:p-6">
|
|
||||||
<div className="flex justify-end pb-2 select-none">
|
|
||||||
<label
|
|
||||||
onClick={() => setStatus(ModalStatus.Default)}
|
|
||||||
htmlFor="learn-more-modal"
|
|
||||||
className="cursor-pointer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="rounded-full p-1 hover:bg-gray-500"
|
|
||||||
src={xButton}
|
|
||||||
alt="learnmore"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className={status === "default" ? "block" : "hidden"}>
|
|
||||||
<div
|
|
||||||
className="w-[100%] bg-gradient-to-r from-primary to-secondary px-6 pt-2 pb-6"
|
|
||||||
data-aos="fade-up"
|
|
||||||
>
|
|
||||||
<h3 className="bg-base-content pt-4 pb-2 text-lg md:text-3xl pt-6">
|
|
||||||
Want to learn more? Get the no-nonsense facts straight from the
|
|
||||||
source
|
|
||||||
</h3>
|
|
||||||
<p className="text-xs bg-base-content md:text-base">
|
|
||||||
Enter your email and we will email you a copy of our Whitepaper
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ModalLearnMoreForm setStatus={setStatus} />
|
|
||||||
</div>
|
|
||||||
{status === ModalStatus.Success && <SuccessModal />}
|
|
||||||
{status === ModalStatus.Loading && <LoadingModal />}
|
|
||||||
</label>
|
|
||||||
</label>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ModalLearnMore;
|
|
|
@ -1,113 +0,0 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
|
||||||
import { learnMoreValidationSchema } from "@/utils/form";
|
|
||||||
import { LearnMoreForm, ModalStatus, SourceModal } from "@/types";
|
|
||||||
import { mailchimp } from "@/app/(auth)/actions";
|
|
||||||
import { toast } from "react-toastify";
|
|
||||||
|
|
||||||
interface ModalLearnMoreFormProps {
|
|
||||||
setStatus: React.Dispatch<React.SetStateAction<ModalStatus>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ModalLearnMoreForm = ({ setStatus }: ModalLearnMoreFormProps) => {
|
|
||||||
const [email, setEmail] = useState("");
|
|
||||||
|
|
||||||
const {
|
|
||||||
register,
|
|
||||||
handleSubmit,
|
|
||||||
reset,
|
|
||||||
formState: { errors },
|
|
||||||
} = useForm({
|
|
||||||
resolver: yupResolver(learnMoreValidationSchema),
|
|
||||||
});
|
|
||||||
|
|
||||||
const submitForm = async (data: LearnMoreForm) => {
|
|
||||||
setEmail(data.email);
|
|
||||||
if (!data.email) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setStatus(ModalStatus.Loading);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await sendMailchimpRequest(data);
|
|
||||||
setEmail("");
|
|
||||||
reset();
|
|
||||||
// await handleSendgridSubmit(data.email);
|
|
||||||
setStatus(ModalStatus.Success);
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof Error) {
|
|
||||||
toast.error(error.message, {
|
|
||||||
position: "bottom-left",
|
|
||||||
autoClose: 5000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true,
|
|
||||||
progress: undefined,
|
|
||||||
theme: "colored",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setStatus(ModalStatus.Default);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendMailchimpRequest = async (data: LearnMoreForm) => {
|
|
||||||
console.log("sendMailchimpRequest call initiated");
|
|
||||||
await mailchimp({
|
|
||||||
email: data.email,
|
|
||||||
first_name: "",
|
|
||||||
last_name: "",
|
|
||||||
phone_number: "",
|
|
||||||
company_size: "",
|
|
||||||
source: SourceModal.LearnMore,
|
|
||||||
});
|
|
||||||
console.log("sendMailchimpRequest call success");
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSendgridSubmit = async (email: string) => {
|
|
||||||
const data = {
|
|
||||||
subscriberEmail: email,
|
|
||||||
};
|
|
||||||
//call to the Netlify Function you created
|
|
||||||
return fetch("./.netlify/functions/triggerLearnMoreEmail", {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
subscriberEmail: data.subscriberEmail,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={handleSubmit(submitForm)} className="w-full md:w-1/2">
|
|
||||||
<div className="relative mt-3 mb-2">
|
|
||||||
<input
|
|
||||||
{...register("email")}
|
|
||||||
id="learnMoreEmail"
|
|
||||||
type="text"
|
|
||||||
className="w-full appearance-none bg-transparent border border-white focus:border-white rounded-sm px-4 mr-2 bg-base-content placeholder-white"
|
|
||||||
placeholder="Your best email…"
|
|
||||||
aria-label="Your best email…"
|
|
||||||
autoComplete="on"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
htmlFor="learnMoreEmail"
|
|
||||||
>
|
|
||||||
{errors.email ? "*" + errors.email.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="btn capitalize font-bold text-black bg-base-100 hover:bg-white shadow"
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ModalLearnMoreForm;
|
|
|
@ -1,117 +0,0 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
import React, { useState, forwardRef, useImperativeHandle } from "react";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
|
||||||
import { signInValidationSchema } from "@/utils/form";
|
|
||||||
import { login } from "@/app/(auth)/actions";
|
|
||||||
import { ModalStatus, SignInForm, TextOnUse } from "@/types";
|
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
export interface FormRefMethods {
|
|
||||||
resetForm: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ModalSignInFormProps {
|
|
||||||
textOnUse: TextOnUse;
|
|
||||||
setStatus: React.Dispatch<React.SetStateAction<ModalStatus>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ModalSignInForm = forwardRef<FormRefMethods, ModalSignInFormProps>(
|
|
||||||
({ textOnUse, setStatus }: ModalSignInFormProps, ref) => {
|
|
||||||
// const context = useContext(Context);
|
|
||||||
const [email, setEmail] = useState("");
|
|
||||||
const [password, setPassword] = useState("");
|
|
||||||
const [organisation, setOrganisation] = useState("");
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const {
|
|
||||||
register,
|
|
||||||
handleSubmit,
|
|
||||||
reset,
|
|
||||||
setError,
|
|
||||||
clearErrors,
|
|
||||||
formState: { errors },
|
|
||||||
} = useForm({
|
|
||||||
resolver: yupResolver(signInValidationSchema),
|
|
||||||
});
|
|
||||||
|
|
||||||
const submitForm = async (data: SignInForm) => {
|
|
||||||
console.log("data", data);
|
|
||||||
clearErrors();
|
|
||||||
setEmail(data.email);
|
|
||||||
setPassword(!data.password ? "" : data.password);
|
|
||||||
setStatus(ModalStatus.Loading);
|
|
||||||
if (!data.password) return;
|
|
||||||
let response = undefined;
|
|
||||||
try {
|
|
||||||
console.log("before login");
|
|
||||||
response = await login({ email: data.email, password: data.password });
|
|
||||||
if (!response.success) {
|
|
||||||
throw new Error(response.error);
|
|
||||||
}
|
|
||||||
const signInModal = document.getElementById("sign-in-modal");
|
|
||||||
if (!!signInModal) signInModal.click();
|
|
||||||
router.push("/account");
|
|
||||||
} catch (error) {
|
|
||||||
setStatus(ModalStatus.Default);
|
|
||||||
console.log(error);
|
|
||||||
setError("email", { type: "custom", message: "Invalid Credentials" });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
useImperativeHandle(ref, () => ({
|
|
||||||
resetForm: () => {
|
|
||||||
reset();
|
|
||||||
setEmail("");
|
|
||||||
setPassword("");
|
|
||||||
setOrganisation("");
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
return (
|
|
||||||
<form onSubmit={handleSubmit(submitForm)} className="w-full md:w-1/2">
|
|
||||||
<div className="relative mt-3">
|
|
||||||
<input
|
|
||||||
{...register("email")}
|
|
||||||
id="SignInEmail"
|
|
||||||
type="text"
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black dark:placeholder-white dark:border-white"
|
|
||||||
placeholder="Your email…"
|
|
||||||
aria-label="Your email…"
|
|
||||||
autoComplete="on"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="SignInEmail"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.email ? "*" + errors.email.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="relative mt-1 mb-4">
|
|
||||||
<input
|
|
||||||
{...register("password")}
|
|
||||||
id="SignInPwd"
|
|
||||||
type="password"
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black dark:placeholder-white dark:border-white"
|
|
||||||
placeholder="Your password..."
|
|
||||||
aria-label="Your password..."
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="SignInPwd"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.password ? "*" + errors.password.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="btn capitalize font-bold text-black bg-base-100 hover:bg-base-100 shadow"
|
|
||||||
>
|
|
||||||
{textOnUse.buttonText}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
ModalSignInForm.displayName = "ModalSignInForm";
|
|
||||||
|
|
||||||
export default ModalSignInForm;
|
|
|
@ -1,317 +0,0 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
import React, {
|
|
||||||
forwardRef,
|
|
||||||
useEffect,
|
|
||||||
useImperativeHandle,
|
|
||||||
useState,
|
|
||||||
} from "react";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
|
||||||
import { signUpValidationSchema } from "@/utils/form";
|
|
||||||
import {
|
|
||||||
login,
|
|
||||||
signup,
|
|
||||||
createCheckoutSession,
|
|
||||||
mailchimp,
|
|
||||||
} from "@/app/(auth)/actions";
|
|
||||||
import { CheckoutSession, ModalStatus, SignUpForm, TextOnUse } from "@/types";
|
|
||||||
import { toast } from "react-toastify";
|
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
import { FormRefMethods } from "../ModalSignIn/ModalSignInForm";
|
|
||||||
|
|
||||||
interface ModalSignUpFormProps {
|
|
||||||
generateCheckoutSession: boolean;
|
|
||||||
textOnUse: TextOnUse;
|
|
||||||
companySizeList: string[];
|
|
||||||
setStatus: React.Dispatch<React.SetStateAction<ModalStatus>>;
|
|
||||||
getPriceId: () => string | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ModalSignUpForm = forwardRef<FormRefMethods, ModalSignUpFormProps>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
generateCheckoutSession,
|
|
||||||
companySizeList,
|
|
||||||
textOnUse,
|
|
||||||
setStatus,
|
|
||||||
getPriceId,
|
|
||||||
}: ModalSignUpFormProps,
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const router = useRouter();
|
|
||||||
const [email, setEmail] = useState("");
|
|
||||||
const [password, setPassword] = useState("");
|
|
||||||
const [organisation, setOrganisation] = useState("");
|
|
||||||
|
|
||||||
const {
|
|
||||||
register,
|
|
||||||
handleSubmit,
|
|
||||||
reset,
|
|
||||||
formState: { errors },
|
|
||||||
} = useForm({
|
|
||||||
resolver: yupResolver(signUpValidationSchema),
|
|
||||||
});
|
|
||||||
|
|
||||||
const submitForm = async (data: SignUpForm) => {
|
|
||||||
setEmail(data.email);
|
|
||||||
setPassword(data.password!);
|
|
||||||
setOrganisation(data.organisation);
|
|
||||||
setStatus(ModalStatus.Loading);
|
|
||||||
try {
|
|
||||||
await sendMailchimpRequest(data);
|
|
||||||
await sendSignUpRequest(data);
|
|
||||||
await sendSignInRequest(data);
|
|
||||||
const price_id = getPriceId();
|
|
||||||
console.log("price_id", price_id);
|
|
||||||
const checkoutSession = await checkoutSessionRequest(price_id);
|
|
||||||
setEmail("");
|
|
||||||
setPassword("");
|
|
||||||
setOrganisation("");
|
|
||||||
reset();
|
|
||||||
setStatus(ModalStatus.Success);
|
|
||||||
if (!!checkoutSession) {
|
|
||||||
router.push(checkoutSession.url);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof Error) {
|
|
||||||
toast.error(error.message, {
|
|
||||||
position: "bottom-left",
|
|
||||||
autoClose: 5000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true,
|
|
||||||
progress: undefined,
|
|
||||||
theme: "colored",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setStatus(ModalStatus.Default);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendMailchimpRequest = async (data: SignUpForm) => {
|
|
||||||
console.log("sendMailchimpRequest call initiated");
|
|
||||||
await mailchimp({
|
|
||||||
email: data.email,
|
|
||||||
first_name: data.first_name,
|
|
||||||
last_name: data.last_name,
|
|
||||||
phone_number: !data.phone_number ? "" : data.phone_number,
|
|
||||||
company_size: data.company_size,
|
|
||||||
source: textOnUse.source,
|
|
||||||
});
|
|
||||||
console.log("sendMailchimpRequest call success");
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkoutSessionRequest = async (price_id?: string) => {
|
|
||||||
if (!price_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log("createCheckoutSession call initiated");
|
|
||||||
const checkoutSession = await createCheckoutSession(price_id);
|
|
||||||
console.log("createCheckoutSession successful");
|
|
||||||
return checkoutSession;
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendSignUpRequest = async (data: SignUpForm) => {
|
|
||||||
try {
|
|
||||||
console.log("Signup call initiated");
|
|
||||||
await signup(data);
|
|
||||||
console.log("Signup successful");
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof Error) {
|
|
||||||
console.error(
|
|
||||||
"Error during the signup or email process:",
|
|
||||||
error.message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw error; // This will allow .catch block outside this function to capture the error
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendSignInRequest = async (data: SignUpForm) => {
|
|
||||||
try {
|
|
||||||
console.log("SignIn call initiated");
|
|
||||||
await login({ email: data.email, password: data.password! });
|
|
||||||
console.log("SignIn successful");
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof Error) {
|
|
||||||
console.error(
|
|
||||||
"Error during the SignIn or email process:",
|
|
||||||
error.message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw error; // This will allow .catch block outside this function to capture the error
|
|
||||||
}
|
|
||||||
};
|
|
||||||
useImperativeHandle(ref, () => ({
|
|
||||||
resetForm: () => {
|
|
||||||
reset();
|
|
||||||
setEmail("");
|
|
||||||
setPassword("");
|
|
||||||
setOrganisation("");
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={handleSubmit(submitForm)} className="w-full md:w-1/2">
|
|
||||||
<div className="relative mt-3">
|
|
||||||
<input
|
|
||||||
{...register("email")}
|
|
||||||
type="text"
|
|
||||||
id="SignUpEmail"
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black dark:placeholder-white dark:border-white"
|
|
||||||
placeholder="Email…"
|
|
||||||
aria-label="Email…"
|
|
||||||
autoComplete="on"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="SignUpEmail"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.email ? "*" + errors.email.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="relative mt-1">
|
|
||||||
<input
|
|
||||||
{...register("first_name")}
|
|
||||||
id="SignUpFirstName"
|
|
||||||
type="text"
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black"
|
|
||||||
placeholder="First Name…"
|
|
||||||
aria-label="First Name…"
|
|
||||||
autoComplete="on"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="SignUpFirstName"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.first_name ? "*" + errors.first_name.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="relative mt-1">
|
|
||||||
<input
|
|
||||||
{...register("last_name")}
|
|
||||||
id="SignUpLastName"
|
|
||||||
type="text"
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black dark:placeholder-white dark:border-white"
|
|
||||||
placeholder="Last Name…"
|
|
||||||
aria-label="Last Name…"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="SignUpLastName"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.last_name ? "*" + errors.last_name.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="relative mt-1">
|
|
||||||
<input
|
|
||||||
{...register("phone_number")}
|
|
||||||
id="SignUpPhoneNumber"
|
|
||||||
type="text"
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black dark:placeholder-white dark:border-white"
|
|
||||||
placeholder="Phone Number…"
|
|
||||||
aria-label="Phone Number…"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="SignUpPhoneNumber"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.phone_number ? "*" + errors.phone_number.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="relative mt-1">
|
|
||||||
<input
|
|
||||||
{...register("organisation")}
|
|
||||||
id="SignUpOrganisation"
|
|
||||||
type="text"
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black dark:placeholder-white dark:border-white"
|
|
||||||
placeholder="Organisation…"
|
|
||||||
aria-label="Organisation…"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="SignUpOrganisation"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.organisation ? "*" + errors.organisation.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="relative mt-1">
|
|
||||||
<select
|
|
||||||
{...register("company_size")}
|
|
||||||
id="SignUpCompanySize"
|
|
||||||
defaultValue={""}
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black dark:placeholder-white dark:border-white"
|
|
||||||
>
|
|
||||||
<option className="bg-gray-850" value={""} disabled>
|
|
||||||
Company Size…
|
|
||||||
</option>
|
|
||||||
{companySizeList.map((companySizeOption, i) => {
|
|
||||||
return (
|
|
||||||
<option
|
|
||||||
className="bg-gray-850"
|
|
||||||
value={companySizeOption}
|
|
||||||
key={i}
|
|
||||||
>
|
|
||||||
{companySizeOption}
|
|
||||||
</option>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</select>
|
|
||||||
<label
|
|
||||||
htmlFor="SignUpCompanySize"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.company_size ? "*" + errors.company_size.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="relative mt-1">
|
|
||||||
<input
|
|
||||||
{...register("password")}
|
|
||||||
id="SignUpPwd"
|
|
||||||
type="password"
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black dark:placeholder-white dark:border-white"
|
|
||||||
placeholder="Password..."
|
|
||||||
aria-label="Password"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="SignUpPwd"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.password ? "*" + errors.password.message : ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="relative mt-1 mb-4">
|
|
||||||
<input
|
|
||||||
{...register("passwordConfirmation")}
|
|
||||||
id="SignUpPwdConfirm"
|
|
||||||
type="password"
|
|
||||||
className="w-full appearance-none bg-transparent border rounded-sm px-4 mr-2 text-black placeholder-black border-black dark:placeholder-white dark:border-white"
|
|
||||||
placeholder="Confirmed Password..."
|
|
||||||
aria-label="Confirmed Password"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="SignUpPwd"
|
|
||||||
className="md:absolute top-[50%] translate-y-[-50%] left-[105%] w-[220px] text-red-400"
|
|
||||||
>
|
|
||||||
{errors.passwordConfirmation
|
|
||||||
? "*" + errors.passwordConfirmation.message
|
|
||||||
: ""}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="btn capitalize font-bold text-black bg-base-100 hover:bg-base-100 shadow"
|
|
||||||
>
|
|
||||||
{textOnUse.buttonText}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ModalSignUpForm.displayName = "ModalSignUpForm";
|
|
||||||
export default ModalSignUpForm;
|
|
|
@ -1,82 +0,0 @@
|
||||||
import { ModalStatus, SourceModal } from '@/types';
|
|
||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
function useTextsBasedOnActivityState(setStatus: React.Dispatch<React.SetStateAction<ModalStatus>>){
|
|
||||||
const signUpTexts = {
|
|
||||||
title: "We Are Growing Fast, and We Want You To Join The Party!",
|
|
||||||
subTitle: "Join our super awesome waitlist and be one of the first to know when spots open up!",
|
|
||||||
buttonText: "Sign Up",
|
|
||||||
netlifyFunction: "triggerSignUpEmail",
|
|
||||||
source: SourceModal.SignUp
|
|
||||||
}
|
|
||||||
|
|
||||||
const signUpViaPurchaseTexts = {
|
|
||||||
title: "Get Ready For Ultimate Productivity",
|
|
||||||
subTitle: "Excited to see what we've got! Signup and get started!",
|
|
||||||
buttonText: "Sign Up",
|
|
||||||
netlifyFunction: "triggerSignUpEmail",
|
|
||||||
source: SourceModal.SignUpViaPurchase
|
|
||||||
}
|
|
||||||
|
|
||||||
const bookDemoTexts = {
|
|
||||||
title: "Get Ready For Ultimate Productivity",
|
|
||||||
subTitle: "Excited to see what we've got! Signup and get started!",
|
|
||||||
buttonText: "Book Now",
|
|
||||||
netlifyFunction: "triggerBookNowEmail",
|
|
||||||
source: SourceModal.BookDemo
|
|
||||||
}
|
|
||||||
|
|
||||||
const TryItTexts = {
|
|
||||||
title: "Get Ready For Ultimate Productivity",
|
|
||||||
subTitle: "Excited to see what we've got! Send us your details and our marketing rep will schedule a demo ASAP.",
|
|
||||||
buttonText: "Try It",
|
|
||||||
netlifyFunction: "triggerBookNowEmail",
|
|
||||||
source: SourceModal.TryIt
|
|
||||||
}
|
|
||||||
|
|
||||||
const [textOnUse, setTextOnUse] = useState(signUpTexts)
|
|
||||||
|
|
||||||
const companySizeList = [
|
|
||||||
"1-10 employees",
|
|
||||||
"10-30 employees",
|
|
||||||
"30-70 employees",
|
|
||||||
"70-100 employees",
|
|
||||||
"100+ employees"
|
|
||||||
]
|
|
||||||
|
|
||||||
const whenModalOpens = () => {
|
|
||||||
const signUpModal = document.getElementById("sign-up-modal");
|
|
||||||
if (!signUpModal) return;
|
|
||||||
const nameAttribute = signUpModal.getAttribute("name");
|
|
||||||
switch(nameAttribute){
|
|
||||||
case SourceModal.BookDemo:
|
|
||||||
setTextOnUse(bookDemoTexts);
|
|
||||||
break;
|
|
||||||
case SourceModal.TryIt:
|
|
||||||
setTextOnUse(TryItTexts);
|
|
||||||
break;
|
|
||||||
case SourceModal.SignUp:
|
|
||||||
setTextOnUse(signUpTexts);
|
|
||||||
break;
|
|
||||||
case SourceModal.SignUpViaPurchase:
|
|
||||||
setTextOnUse(signUpViaPurchaseTexts)
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setTextOnUse(bookDemoTexts);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
setTimeout(() => setStatus(ModalStatus.Default), 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
const getPriceId = () => {
|
|
||||||
const signUpModal = document.getElementById("sign-up-modal");
|
|
||||||
if (!signUpModal) return undefined;
|
|
||||||
const price_id = signUpModal.getAttribute("price_id");
|
|
||||||
if (!price_id) return undefined;
|
|
||||||
return price_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {textOnUse, companySizeList, whenModalOpens, getPriceId}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useTextsBasedOnActivityState;
|
|
|
@ -5,7 +5,6 @@ import { NewsLetterForm, SourceModal } from "@/types";
|
||||||
import { mailchimp } from "@/app/(auth)/actions";
|
import { mailchimp } from "@/app/(auth)/actions";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import { ModalStatus } from "@/types";
|
import { ModalStatus } from "@/types";
|
||||||
import Button from "@/components/Button";
|
|
||||||
|
|
||||||
const NewsletterForm = () => {
|
const NewsletterForm = () => {
|
||||||
const [status, setStatus] = useState<ModalStatus>(ModalStatus.Default);
|
const [status, setStatus] = useState<ModalStatus>(ModalStatus.Default);
|
||||||
|
@ -77,7 +76,7 @@ const NewsletterForm = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mb-6 lg:mr-16 lg:mb-0 text-center lg:text-left lg:w-1/2">
|
<div className="mb-6 lg:mr-16 lg:mb-0 text-center lg:text-left lg:w-1/2 text-primary-content">
|
||||||
<h3 className=" mb-2 text-3xl font-black">
|
<h3 className=" mb-2 text-3xl font-black">
|
||||||
{status !== ModalStatus.Success
|
{status !== ModalStatus.Success
|
||||||
? "Stay Ahead of the Curve"
|
? "Stay Ahead of the Curve"
|
||||||
|
@ -93,9 +92,17 @@ const NewsletterForm = () => {
|
||||||
<div className="w-full lg:w-1/2">
|
<div className="w-full lg:w-1/2">
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => submitForm(e)}
|
onSubmit={(e) => submitForm(e)}
|
||||||
className="flex flex-col sm:flex-row justify-center max-w-xs mx-auto sm:max-w-md lg:max-w-none"
|
className="flex flex-col sm:flex-row justify-center max-w-xs mx-auto sm:max-w-md lg:max-w-none gap-x-2"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
|
id="NewsletterEmail"
|
||||||
|
type="text"
|
||||||
|
className="py-3 px-4 block w-full text-base-content border-white rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none "
|
||||||
|
placeholder="Email…"
|
||||||
|
aria-label="Email…"
|
||||||
|
// {...register("email")}
|
||||||
|
/>
|
||||||
|
{/* <input
|
||||||
required
|
required
|
||||||
name="email"
|
name="email"
|
||||||
type="email"
|
type="email"
|
||||||
|
@ -106,22 +113,8 @@ const NewsletterForm = () => {
|
||||||
aria-label="Your best email…"
|
aria-label="Your best email…"
|
||||||
disabled={status === ModalStatus.Success}
|
disabled={status === ModalStatus.Success}
|
||||||
autoComplete="on"
|
autoComplete="on"
|
||||||
/>
|
/> */}
|
||||||
<Button
|
<button className="btn btn-primary">Subscribe</button>
|
||||||
status={status}
|
|
||||||
text={(() => {
|
|
||||||
switch (status) {
|
|
||||||
case ModalStatus.Loading:
|
|
||||||
return "Sending...";
|
|
||||||
case ModalStatus.Success:
|
|
||||||
return "Success";
|
|
||||||
case ModalStatus.Default:
|
|
||||||
return "Subscribe";
|
|
||||||
default:
|
|
||||||
return "default-class";
|
|
||||||
}
|
|
||||||
})()}
|
|
||||||
/>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -7,7 +7,7 @@ interface PageHeaderProps {
|
||||||
function PageHeader({ title, subtitle }: PageHeaderProps) {
|
function PageHeader({ title, subtitle }: PageHeaderProps) {
|
||||||
return (
|
return (
|
||||||
<div className="pt-28 max-w-screen flex flex-col">
|
<div className="pt-28 max-w-screen flex flex-col">
|
||||||
<h1 className="text-5xl font-black text-base-content mb-12 mx-auto">
|
<h1 className="text-5xl font-bold text-base-content mb-6 mx-auto">
|
||||||
{title}
|
{title}
|
||||||
</h1>
|
</h1>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Architects+Daughter&family=Inter:wght@400;500;600;700;800;900&display=fallback');
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Arimo:wght@400;500;600;700;800;900&display=fallback');
|
|
||||||
|
|
||||||
@import 'tailwindcss/base';
|
|
||||||
@import 'tailwindcss/components';
|
|
||||||
|
|
||||||
@import 'tailwindcss/utilities';
|
|
||||||
|
|
||||||
/* Additional Tailwind directives: https://tailwindcss.com/docs/functions-and-directives/#responsive */
|
|
||||||
@layer utilities {
|
|
||||||
.rtl {
|
|
||||||
direction: rtl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See Alpine.js: https://github.com/alpinejs/alpine#x-cloak */
|
|
||||||
[x-cloak=""] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
|
@ -11,57 +11,9 @@ const config: Config = {
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
|
||||||
gray: {
|
|
||||||
100: "#EBF1F5",
|
|
||||||
200: "#D9E3EA",
|
|
||||||
300: "#C5D2DC",
|
|
||||||
400: "#9BA9B4",
|
|
||||||
500: "#707D86",
|
|
||||||
550: "#52485B",
|
|
||||||
600: "#55595F",
|
|
||||||
650: "#4c5058",
|
|
||||||
700: "#33363A",
|
|
||||||
800: "#25282C",
|
|
||||||
825: "#34363A",
|
|
||||||
850: "#383040",
|
|
||||||
900: "#151719",
|
|
||||||
925: "#191D24",
|
|
||||||
950: "#000000",
|
|
||||||
},
|
|
||||||
purple: {
|
|
||||||
default: "#8000FF",
|
|
||||||
100: "#F4F4FF",
|
|
||||||
200: "#E2E1FF",
|
|
||||||
300: "#CBCCFF",
|
|
||||||
400: "#ABABFF",
|
|
||||||
500: "#8D8DFF",
|
|
||||||
600: "#5D5DFF",
|
|
||||||
700: "#4B4ACF",
|
|
||||||
800: "#38379C",
|
|
||||||
900: "#262668",
|
|
||||||
},
|
|
||||||
pink: {
|
|
||||||
default: "#FF0DCA",
|
|
||||||
500: "#D18DFF",
|
|
||||||
550: "#8A4CC8",
|
|
||||||
600: "#AB4FD7",
|
|
||||||
700: "#7a2ec5",
|
|
||||||
900: "#3C3445",
|
|
||||||
},
|
|
||||||
red: {
|
|
||||||
300: "#C84C4C",
|
|
||||||
600: "#8b2e2e",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
spacing: {
|
|
||||||
"9/16": "56.25%",
|
|
||||||
"3/4": "75%",
|
|
||||||
"1/1": "100%",
|
|
||||||
},
|
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
primary: ["Raleway Variable", ...defaultTheme.fontFamily.sans],
|
heading: 'var(--heading-font)',
|
||||||
secondary: ["Arimo Variable", ...defaultTheme.fontFamily.sans],
|
body: 'var(--heading-font)',
|
||||||
},
|
},
|
||||||
fontSize: {
|
fontSize: {
|
||||||
xs: "0.75rem",
|
xs: "0.75rem",
|
||||||
|
@ -75,9 +27,6 @@ const config: Config = {
|
||||||
"5xl": "3.25rem",
|
"5xl": "3.25rem",
|
||||||
"6xl": "4rem",
|
"6xl": "4rem",
|
||||||
},
|
},
|
||||||
inset: {
|
|
||||||
full: "100%",
|
|
||||||
},
|
|
||||||
letterSpacing: {
|
letterSpacing: {
|
||||||
tighter: "-0.02em",
|
tighter: "-0.02em",
|
||||||
tight: "-0.01em",
|
tight: "-0.01em",
|
||||||
|
@ -86,12 +35,33 @@ const config: Config = {
|
||||||
wider: "0.02em",
|
wider: "0.02em",
|
||||||
widest: "0.4em",
|
widest: "0.4em",
|
||||||
},
|
},
|
||||||
minWidth: {
|
typography: {
|
||||||
"10": "2.5rem",
|
DEFAULT: {
|
||||||
},
|
css: {
|
||||||
scale: {
|
p: {
|
||||||
"98": ".98",
|
fontFamily: 'var(--body-font)'
|
||||||
},
|
},
|
||||||
|
h1: {
|
||||||
|
fontFamily: 'var(--heading-font)'
|
||||||
|
},
|
||||||
|
h2: {
|
||||||
|
fontFamily: 'var(--heading-font)'
|
||||||
|
},
|
||||||
|
h3: {
|
||||||
|
fontFamily: 'var(--heading-font)'
|
||||||
|
},
|
||||||
|
h4: {
|
||||||
|
fontFamily: 'var(--heading-font)'
|
||||||
|
},
|
||||||
|
h5: {
|
||||||
|
fontFamily: 'var(--heading-font)'
|
||||||
|
},
|
||||||
|
h6: {
|
||||||
|
fontFamily: 'var(--heading-font)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
daisyui: {
|
daisyui: {
|
||||||
|
|
Loading…
Reference in New Issue