From e356a5248350c4d0c92d2e710e4bc0a35a17151a Mon Sep 17 00:00:00 2001 From: Ayodejioladimeji Date: Wed, 24 Jul 2024 14:32:35 +0100 Subject: [PATCH 1/4] added homepage changes and tests --- .../layouts/homepage/HowItWorks.tsx | 6 +- .../layouts/homepage/Testimonials.tsx | 6 +- src/test/homepage/Hero.test.tsx | 75 +++++++++++++++++++ src/test/homepage/HowItWorks.test.tsx | 75 +++++++++++++++++++ src/test/homepage/PerfectFit.test.tsx | 47 ++++++++++++ src/test/homepage/TestimonialCard.test.tsx | 58 ++++++++++++++ src/test/homepage/Testimonials.test.tsx | 54 +++++++++++++ src/test/homepage/UserSection.test.tsx | 57 ++++++++++++++ 8 files changed, 372 insertions(+), 6 deletions(-) create mode 100644 src/test/homepage/Hero.test.tsx create mode 100644 src/test/homepage/HowItWorks.test.tsx create mode 100644 src/test/homepage/PerfectFit.test.tsx create mode 100644 src/test/homepage/TestimonialCard.test.tsx create mode 100644 src/test/homepage/Testimonials.test.tsx create mode 100644 src/test/homepage/UserSection.test.tsx diff --git a/src/components/layouts/homepage/HowItWorks.tsx b/src/components/layouts/homepage/HowItWorks.tsx index b74c1b604..ba5f78bb5 100644 --- a/src/components/layouts/homepage/HowItWorks.tsx +++ b/src/components/layouts/homepage/HowItWorks.tsx @@ -22,7 +22,7 @@ const HowItWorks = () => {

Pre-Built Sections @@ -42,7 +42,7 @@ const HowItWorks = () => {

Scalable Foundation @@ -63,7 +63,7 @@ const HowItWorks = () => {

Easy Customization diff --git a/src/components/layouts/homepage/Testimonials.tsx b/src/components/layouts/homepage/Testimonials.tsx index c86ae95bd..52dd8f6eb 100644 --- a/src/components/layouts/homepage/Testimonials.tsx +++ b/src/components/layouts/homepage/Testimonials.tsx @@ -53,7 +53,7 @@ const Testimonials = () => { { }, 650: { slidesPerView: 2, - spaceBetween: 30, + spaceBetween: 20, }, 1024: { slidesPerView: 3, - spaceBetween: 30, + spaceBetween: 20, }, }} data-testid="swiper" diff --git a/src/test/homepage/Hero.test.tsx b/src/test/homepage/Hero.test.tsx new file mode 100644 index 000000000..a6c05b2f6 --- /dev/null +++ b/src/test/homepage/Hero.test.tsx @@ -0,0 +1,75 @@ +import { render, screen } from "@testing-library/react"; + +import "@testing-library/jest-dom"; + +import Hero from "~/components/layouts/homepage/Hero"; + +describe("hero Component", () => { + it("renders the hero heading", () => { + expect.assertions(1); // Ensure exactly one assertion + + render(); + const heading = screen.getByRole("heading", { + name: /focus on what matters. we've got the foundation covered./i, + }); + expect(heading).toBeInTheDocument(); + }); + + it("renders the hero paragraph", () => { + expect.assertions(1); // Ensure exactly one assertion + + render(); + const paragraph = screen.getByText( + /streamline your processes with a boilerplate built for efficiency and optimal productivity./i, + ); + expect(paragraph).toBeInTheDocument(); + }); + + it("renders the get started button", () => { + expect.assertions(1); // Ensure exactly one assertion + + render(); + const button = screen.getByRole("button", { name: /get started/i }); + expect(button).toBeInTheDocument(); + }); + + it("renders the HeroCheckMark component", () => { + expect.assertions(1); // Ensure exactly one assertion + + render(); + const checkMark = screen.getByTestId("hero-checkmark"); + expect(checkMark).toBeInTheDocument(); + }); + + it("renders the HeroChat component", () => { + expect.assertions(1); // Ensure exactly one assertion + + render(); + const chat = screen.getByTestId("hero-chat"); + expect(chat).toBeInTheDocument(); + }); + + it("renders the HeroBoilerPlate component", () => { + expect.assertions(1); // Ensure exactly one assertion + + render(); + const boilerPlate = screen.getByTestId("hero-boilerplate"); + expect(boilerPlate).toBeInTheDocument(); + }); + + it("renders the Swiper component", () => { + expect.assertions(1); // Ensure exactly one assertion + + render(); + const swiper = screen.getByTestId("swiper"); + expect(swiper).toBeInTheDocument(); + }); + + it("renders all Swiper slides", () => { + expect.assertions(1); // Ensure exactly one assertion + + render(); + const slides = screen.getAllByAltText("Hero Image"); + expect(slides).toHaveLength(6); + }); +}); diff --git a/src/test/homepage/HowItWorks.test.tsx b/src/test/homepage/HowItWorks.test.tsx new file mode 100644 index 000000000..0ba9a3e82 --- /dev/null +++ b/src/test/homepage/HowItWorks.test.tsx @@ -0,0 +1,75 @@ +import { render, screen } from "@testing-library/react"; + +import "@testing-library/jest-dom"; + +import HowItWorks from "~/components/layouts/homepage/HowItWorks"; + +describe("howItWorks Component", () => { + it("renders the heading", () => { + expect.assertions(1); + + render(); + const heading = screen.getByRole("heading", { + name: /how it works: experience the benefits of using our product with every step./i, + }); + expect(heading).toBeInTheDocument(); + }); + + it("renders the description paragraph", () => { + expect.assertions(1); + + render(); + const paragraph = screen.getByText( + /we designed our product to simplify your life. it offers a comprehensive solution. here's how it works and how it benefits you at each stage./i, + ); + expect(paragraph).toBeInTheDocument(); + }); + + it("renders the Pre-Built component", () => { + expect.assertions(1); + + render(); + const preBuilt = screen.getByTestId("prebuilt"); + expect(preBuilt).toBeInTheDocument(); + }); + + it("renders the Sections component", () => { + expect.assertions(1); + + render(); + const preBuiltDescription = screen.getByTestId("section"); + expect(preBuiltDescription).toBeInTheDocument(); + }); + + it("renders the Scalable component", () => { + expect.assertions(1); + + render(); + const scalable = screen.getByTestId("scalable"); + expect(scalable).toBeInTheDocument(); + }); + + it("renders the Foundation component", () => { + expect.assertions(1); + + render(); + const scalableDescription = screen.getByTestId("boilerplate"); + expect(scalableDescription).toBeInTheDocument(); + }); + + it("renders the Easy component", () => { + expect.assertions(1); + + render(); + const easyCustomization = screen.getByTestId("easy"); + expect(easyCustomization).toBeInTheDocument(); + }); + + it("renders the Customization component", () => { + expect.assertions(1); + + render(); + const easyCustomizationDescription = screen.getByTestId("tailor"); + expect(easyCustomizationDescription).toBeInTheDocument(); + }); +}); diff --git a/src/test/homepage/PerfectFit.test.tsx b/src/test/homepage/PerfectFit.test.tsx new file mode 100644 index 000000000..6dfa66f73 --- /dev/null +++ b/src/test/homepage/PerfectFit.test.tsx @@ -0,0 +1,47 @@ +import { render, screen } from "@testing-library/react"; + +import "@testing-library/jest-dom"; + +import PerfectFit from "~/components/layouts/homepage/PerfectFit"; + +describe("perfectFit Component", () => { + it("renders the heading", () => { + expect.assertions(1); + + render(); + const heading = screen.getByRole("heading", { + name: /find the perfect fit/i, + }); + expect(heading).toBeInTheDocument(); + }); + + it("renders the paragraph", () => { + expect.assertions(1); + + render(); + const paragraph = screen.getByText( + /choose the boilerplate plan that best suits your project needs and budget. all plans include access to our comprehensive library of pre-built sections, drag-and-drop customization./i, + ); + expect(paragraph).toBeInTheDocument(); + }); + + it("renders the See Our Pricing Plan button", () => { + expect.assertions(1); + + render(); + const button = screen.getByRole("button", { + name: /see our pricing plan/i, + }); + expect(button).toBeInTheDocument(); + }); + + it("applies the correct text color to the paragraph", () => { + expect.assertions(1); + + render(); + const paragraph = screen.getByText( + /choose the boilerplate plan that best suits your project needs and budget. all plans include access to our comprehensive library of pre-built sections, drag-and-drop customization./i, + ); + expect(paragraph).toHaveClass("text-[#525252]"); + }); +}); diff --git a/src/test/homepage/TestimonialCard.test.tsx b/src/test/homepage/TestimonialCard.test.tsx new file mode 100644 index 000000000..08c3ca724 --- /dev/null +++ b/src/test/homepage/TestimonialCard.test.tsx @@ -0,0 +1,58 @@ +import { render, screen } from "@testing-library/react"; + +import "@testing-library/jest-dom"; + +import TestimonialCard from "~/components/layouts/homepage/TestimonialCard"; + +describe("testimonialCard Component", () => { + const properties = { + image: "/images/testimonial-image.svg", + content: + "“I've been using this web hosting service for over a year and I'm really impressed with the uptime and support. The website has never gone down and the customer service is always quick to help with any issues I have. Highly recommend!”", + name: "John Doe", + stack: "Full Stack Developer", + }; + + it("renders the testimonial content", () => { + expect.assertions(1); + + render(); + const content = screen.getByText( + /i've been using this web hosting service for over a year and i'm really impressed with the uptime and support./i, + ); + expect(content).toBeInTheDocument(); + }); + + it("renders the testimonial name", () => { + expect.assertions(1); + + render(); + const name = screen.getByText(properties.name); + expect(name).toBeInTheDocument(); + }); + + it("renders the testimonial stack", () => { + expect.assertions(1); + + render(); + const stack = screen.getByText(properties.stack); + expect(stack).toBeInTheDocument(); + }); + + it("renders the image with the correct src and alt attributes", () => { + expect.assertions(2); + + render(); + const image = screen.getByAltText("testimonial-image"); + expect(image).toHaveAttribute("src", properties.image); + expect(image).toHaveAttribute("alt", "testimonial-image"); + }); + + it("renders the Rating component", () => { + expect.assertions(1); + + render(); + const rating = screen.getByTestId("rating"); + expect(rating).toBeInTheDocument(); + }); +}); diff --git a/src/test/homepage/Testimonials.test.tsx b/src/test/homepage/Testimonials.test.tsx new file mode 100644 index 000000000..996a66d5d --- /dev/null +++ b/src/test/homepage/Testimonials.test.tsx @@ -0,0 +1,54 @@ +import { render, screen } from "@testing-library/react"; + +import "@testing-library/jest-dom"; + +import Testimonials from "~/components/layouts/homepage/Testimonials"; +import { testimonials } from "~/components/layouts/homepage/testimonials-data"; + +describe("testimonials Component", () => { + it("renders the testimonials heading", () => { + expect.assertions(1); + + render(); + const heading = screen.getByRole("heading", { + name: /client testimonials/i, + }); + expect(heading).toBeInTheDocument(); + }); + + it("renders the testimonials paragraph", () => { + expect.assertions(1); + + render(); + const paragraph = screen.getByText( + /don't just take our word for it - see what actual users of our product have to say about their experience./i, + ); + expect(paragraph).toBeInTheDocument(); + }); + + it("renders the navigation buttons", () => { + expect.assertions(2); + + render(); + const previousButton = screen.getByTestId("custom-prev"); + const nextButton = screen.getByTestId("custom-next"); + expect(previousButton).toBeInTheDocument(); + expect(nextButton).toBeInTheDocument(); + }); + + it("renders the Swiper component with testimonials", () => { + expect.assertions(1); + + render(); + const testimonialCards = screen.getAllByTestId("testimonial-card"); + expect(testimonialCards.length).toBeGreaterThan(0); + }); + + it("renders the correct number of Swiper slides", () => { + expect.assertions(1); + + render(); + const slides = screen.getAllByRole("group"); + expect(slides).toHaveLength(testimonials.length); + }); +}); diff --git a/src/test/homepage/UserSection.test.tsx b/src/test/homepage/UserSection.test.tsx new file mode 100644 index 000000000..b0e239ca6 --- /dev/null +++ b/src/test/homepage/UserSection.test.tsx @@ -0,0 +1,57 @@ +import { render, screen } from "@testing-library/react"; + +import "@testing-library/jest-dom"; + +import UserSection from "~/components/layouts/homepage/UserSection"; + +describe("userSection Component", () => { + it("renders the heading with the correct text", () => { + expect.assertions(1); + + render(); + const heading = screen.getByRole("heading", { + name: /more than 200 users make use of our boilerplate/i, + }); + expect(heading).toBeInTheDocument(); + }); + + it("renders the Unsplash logo", () => { + expect.assertions(1); + + render(); + const unsplash = screen.getByTestId("unsplash-logo"); + expect(unsplash).toBeInTheDocument(); + }); + + it("renders the Notion logo", () => { + expect.assertions(1); + + render(); + const notion = screen.getByTestId("notion-logo"); + expect(notion).toBeInTheDocument(); + }); + + it("renders the Intercom logo", () => { + expect.assertions(1); + + render(); + const intercom = screen.getByTestId("intercom-logo"); + expect(intercom).toBeInTheDocument(); + }); + + it("renders the Descript logo", () => { + expect.assertions(1); + + render(); + const descript = screen.getByTestId("descript-logo"); + expect(descript).toBeInTheDocument(); + }); + + it("renders the Grammarly logo", () => { + expect.assertions(1); + + render(); + const grammarly = screen.getByTestId("grammarly-logo"); + expect(grammarly).toBeInTheDocument(); + }); +}); From 0833af030fd33557aa312cbaf1d11c02bf9b69a0 Mon Sep 17 00:00:00 2001 From: Ayodejioladimeji Date: Wed, 24 Jul 2024 15:04:11 +0100 Subject: [PATCH 2/4] added pricing model page --- public/images/checkmark.svg | 3 + src/app/(landing-routes)/pricing/page.tsx | 538 ++++++++++++++++++ .../layouts/accordion/FaqsAccordion.tsx | 57 ++ .../layouts/accordion/TopicAccordion.tsx | 42 ++ .../layouts/careercard/CareerCard.tsx | 65 +++ src/components/layouts/careercard/index.tsx | 29 + src/components/layouts/navbar/index.tsx | 2 +- .../layouts/pagination/Pagination.tsx | 130 +++++ src/constants/faqsdata.ts | 17 + src/constants/templateList.ts | 27 + src/constants/topicsdata.ts | 47 ++ src/test/pricingpage/pricing.test.tsx | 38 ++ 12 files changed, 994 insertions(+), 1 deletion(-) create mode 100644 public/images/checkmark.svg create mode 100644 src/app/(landing-routes)/pricing/page.tsx create mode 100644 src/components/layouts/accordion/FaqsAccordion.tsx create mode 100644 src/components/layouts/accordion/TopicAccordion.tsx create mode 100644 src/components/layouts/careercard/CareerCard.tsx create mode 100644 src/components/layouts/careercard/index.tsx create mode 100644 src/components/layouts/pagination/Pagination.tsx create mode 100644 src/constants/faqsdata.ts create mode 100644 src/constants/templateList.ts create mode 100644 src/constants/topicsdata.ts create mode 100644 src/test/pricingpage/pricing.test.tsx diff --git a/public/images/checkmark.svg b/public/images/checkmark.svg new file mode 100644 index 000000000..90773421d --- /dev/null +++ b/public/images/checkmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/app/(landing-routes)/pricing/page.tsx b/src/app/(landing-routes)/pricing/page.tsx new file mode 100644 index 000000000..ddc871d6a --- /dev/null +++ b/src/app/(landing-routes)/pricing/page.tsx @@ -0,0 +1,538 @@ +"use client"; + +import Image from "next/image"; +import { useState } from "react"; + +import FaqAccordion from "~/components/layouts/accordion/FaqsAccordion"; +import { Button } from "~/components/ui/button"; +import { faqData } from "~/constants/faqsdata"; + +// + +const handleButtonClickTest = () => { + alert("Contact Button Click Test"); +}; + +// + +export default function Pricing() { + const [toggle, setToggle] = useState(1); + + return ( + <> +
+
+

+ Pricing +

+ +

+ Simple and Affordable{" "} + Pricing Plan +

+

+ Our flexible plans are designed to scale with your business. We have + a plan for you. +

+
+ +
+
setToggle(1)} + className={`flex h-[50px] w-[190px] cursor-pointer items-center justify-center rounded-md ${toggle === 1 ? "bg-white font-medium" : ""}`} + data-testid="monthly-toggle" + > + Monthly +
+
setToggle(2)} + className={`flex h-[50px] w-[190px] cursor-pointer items-center justify-center rounded-md ${toggle === 2 ? "bg-white font-medium" : ""}`} + data-testid="annual-toggle" + > + Annual(save 20%) +
+
+ +
+ {toggle === 1 ? ( + <> +
+

+ Basic +

+

+ $800 /month +

+

+ The essensitals to provide your best work for clients. +

+
+ + 2 Projects +
+
+ + Up to 100 subscribers +
+
+ + Basic analytics +
+
+ + 24-hour support response time +
+
+ + Marketing advisor +
+
+ + Custom integration +
+ +
+ +
+

+ Premium +

+

+ $3,000 /month +

+

+ The essensitals to provide your best work for clients. +

+
+ + 2 Projects +
+
+ + Up to 100 subscribers +
+
+ + Basic analytics +
+
+ + 24-hour support response time +
+
+ + Marketing advisor +
+
+ + Custom integration +
+ +
+ + ) : ( + <> +
+

+ Basic +

+

+ $500 /month +

+

+ The essensitals to provide your best work for clients. +

+
+ + 2 Projects +
+
+ + Up to 100 subscribers +
+
+ + Basic analytics +
+
+ + 24-hour support response time +
+
+ + Marketing advisor +
+
+ + Custom integration +
+ +
+ +
+

+ Premium +

+

+ $2,000 /month +

+

+ The essensitals to provide your best work for clients. +

+
+ + 2 Projects +
+
+ + Up to 100 subscribers +
+
+ + Basic analytics +
+
+ + 24-hour support response time +
+
+ + Marketing advisor +
+
+ + Custom integration +
+ +
+ + )} +
+
+ +
+
+
+
+

+ Frequently Asked Questions +

+ +

+ We couldn’t answer your question? +

+ + +
+ + +
+
+
+ + ); +} diff --git a/src/components/layouts/accordion/FaqsAccordion.tsx b/src/components/layouts/accordion/FaqsAccordion.tsx new file mode 100644 index 000000000..35841a8ac --- /dev/null +++ b/src/components/layouts/accordion/FaqsAccordion.tsx @@ -0,0 +1,57 @@ +import clsx from "clsx"; + +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "~/components/ui/accordion"; + +interface FaqAccordionProperties { + faqs: { question: string; content: string }[]; // Define the shape of faq objects + containerClassName?: string; + triggerClassName?: string; + contentClassName?: string; +} + +const FaqAccordion = ({ + faqs, + triggerClassName, + contentClassName, + containerClassName, +}: FaqAccordionProperties) => { + return ( +
+ + {faqs?.map((faq, index) => ( + + + {faq.question} + + + {faq.content} + + + ))} + +
+ ); +}; + +export default FaqAccordion; diff --git a/src/components/layouts/accordion/TopicAccordion.tsx b/src/components/layouts/accordion/TopicAccordion.tsx new file mode 100644 index 000000000..f286ed4fd --- /dev/null +++ b/src/components/layouts/accordion/TopicAccordion.tsx @@ -0,0 +1,42 @@ +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "~/components/ui/accordion"; +import { topics } from "~/constants/topicsdata"; + +const TopicsAccordions = () => { + return ( + + {topics.map((topic, index) => ( + + + {topic.question} + + + {topic.answer} + + + ))} + + ); +}; + +export default TopicsAccordions; diff --git a/src/components/layouts/careercard/CareerCard.tsx b/src/components/layouts/careercard/CareerCard.tsx new file mode 100644 index 000000000..74a556aa1 --- /dev/null +++ b/src/components/layouts/careercard/CareerCard.tsx @@ -0,0 +1,65 @@ +import { FC } from "react"; + +import { Card, CardContent, CardFooter } from "~/components/ui/card"; +import { Skeleton } from "~/components/ui/skeleton"; +import CustomButton from "../Button/button"; + +interface CareerCardProperties { + isLoading: boolean; + jobTitle?: string; + location?: string; + description?: string; + amount?: string; +} + +const CareerCard: FC = ({ + isLoading, + jobTitle, + location, + description, + amount, +}) => { + return ( + + + {isLoading ? ( +
+ +
+ + +
+
+ ) : ( + <> +

{jobTitle}

+

{location}

+

{description}

+ + )} +
+ + + {isLoading ? ( + <> + + + + ) : ( + <> + + {amount} + /month + + View Details + + )} + +
+ ); +}; + +export default CareerCard; diff --git a/src/components/layouts/careercard/index.tsx b/src/components/layouts/careercard/index.tsx new file mode 100644 index 000000000..737247a3b --- /dev/null +++ b/src/components/layouts/careercard/index.tsx @@ -0,0 +1,29 @@ +"use client"; + +import { FC, useEffect, useState } from "react"; + +import CareerCard from "./CareerCard"; + +const CareerCardParent: FC = () => { + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + const timer = setTimeout(() => { + setIsLoading(false); + }, 2000); + + return () => clearTimeout(timer); + }, []); + + return ( + + ); +}; + +export default CareerCardParent; diff --git a/src/components/layouts/navbar/index.tsx b/src/components/layouts/navbar/index.tsx index 1aa285f11..f2f17be2b 100644 --- a/src/components/layouts/navbar/index.tsx +++ b/src/components/layouts/navbar/index.tsx @@ -9,7 +9,7 @@ import Logo from "~/components/common/logo"; const navlinks = [ { route: "Home", link: "/" }, - { route: "Pricing", link: "/" }, + { route: "Pricing", link: "/pricing" }, { route: "Features", link: "/" }, ]; diff --git a/src/components/layouts/pagination/Pagination.tsx b/src/components/layouts/pagination/Pagination.tsx new file mode 100644 index 000000000..518f63d46 --- /dev/null +++ b/src/components/layouts/pagination/Pagination.tsx @@ -0,0 +1,130 @@ +"use client"; + +import { + Pagination as PaginationComponent, + PaginationContent, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from "~/components/ui/pagination"; + +export interface PaginationProperties { + total: number; + pageSize: number; + currentPage: number; + activeVariant?: "default" | "outline"; + navigationVariant?: "semibold" | "medium"; + onChange?: (page: number) => void; +} + +const Pagination = ({ + total, + pageSize, + currentPage, + activeVariant = "default", + navigationVariant = "medium", + onChange, +}: PaginationProperties) => { + const totalPages = Math.ceil(total / pageSize); + + const handleChange = (page: number) => { + if (onChange) { + onChange(page); + } + }; + + const getPageNumbers = () => { + const pages = []; + const showEllipsis = totalPages > 3; + + if (showEllipsis === false) { + for (let index = 1; index <= totalPages; index++) { + pages.push(index); + } + } else { + pages.push(1); + if (currentPage > 4) { + pages.push("..."); + } + + const firstPage = Math.max(2, currentPage - 2); + const lastPage = Math.min(totalPages - 1, currentPage + 2); + + for (let index = firstPage; index <= lastPage; index++) { + pages.push(index); + } + + if (currentPage < totalPages - 3) { + pages.push("..."); + } + pages.push(totalPages); + } + + return pages; + }; + + return ( + + + + currentPage > 1 && handleChange(currentPage - 1)} + className={`${ + navigationVariant === "semibold" + ? "text-xl font-semibold leading-normal" + : "text-base font-medium leading-6" + } ${ + currentPage > 1 + ? "cursor-pointer" + : "cursor-not-allowed text-stroke-colors-stroke hover:bg-transparent hover:text-stroke-colors-stroke" + }`} + href={currentPage > 1 ? `?page=${currentPage - 1}` : "#"} + /> + + {getPageNumbers().map((page, index) => + typeof page === "number" ? ( + handleChange(page)}> + + {page} + + + ) : ( + + {page} + + ), + )} + + currentPage < totalPages && handleChange(currentPage + 1) + } + > + + + + + ); +}; + +export default Pagination; diff --git a/src/constants/faqsdata.ts b/src/constants/faqsdata.ts new file mode 100644 index 000000000..3ef833759 --- /dev/null +++ b/src/constants/faqsdata.ts @@ -0,0 +1,17 @@ +export const faqData = [ + { + question: "What is the purpose of this application?", + content: + "This application is designed to help users manage their tasks efficiently by providing tools for scheduling, tracking progress, and setting reminders.", + }, + { + question: "How do I reset my password?", + content: + "To reset your password, go to the login page and click on the 'Forgot Password' link. Follow the instructions to receive a password reset email and create a new password.", + }, + { + question: "Can I use this application on multiple devices?", + content: + "Yes, the application is accessible from multiple devices including desktops, tablets, and smartphones. Your data will be synced across all devices, ensuring a seamless experience.", + }, +]; diff --git a/src/constants/templateList.ts b/src/constants/templateList.ts new file mode 100644 index 000000000..72d424ee8 --- /dev/null +++ b/src/constants/templateList.ts @@ -0,0 +1,27 @@ +const templateTableList = [ + { id: 1, name: "Alani", image: "" }, + { id: 2, name: "Alani1", image: "" }, + { id: 3, name: "Alani2", image: "" }, + { id: 4, name: "Alani3", image: "" }, + { id: 5, name: "Alani4", image: "" }, + { id: 6, name: "Alani5", image: "" }, + { id: 7, name: "Alani6", image: "" }, + { id: 8, name: "Alani7", image: "" }, + { id: 9, name: "Alani8", image: "" }, + { id: 10, name: "Alani9", image: "" }, + { id: 11, name: "Alani10", image: "" }, + { id: 12, name: "Alani11", image: "" }, + { id: 13, name: "Alani12", image: "" }, + { id: 14, name: "Alani13", image: "" }, + { id: 15, name: "Alani14", image: "" }, + { id: 16, name: "Alani15", image: "" }, + { id: 17, name: "Alani16", image: "" }, + { id: 18, name: "Alani17", image: "" }, + { id: 19, name: "Alani18", image: "" }, + { id: 20, name: "Alani19", image: "" }, + { id: 21, name: "Alani20", image: "" }, + { id: 22, name: "Alani21", image: "" }, + { id: 23, name: "Alani22", image: "" }, +]; + +export default templateTableList; diff --git a/src/constants/topicsdata.ts b/src/constants/topicsdata.ts new file mode 100644 index 000000000..e5b61e58a --- /dev/null +++ b/src/constants/topicsdata.ts @@ -0,0 +1,47 @@ +export const topics = [ + { + id: "item-1", + question: "What is EcoClean?", + answer: "Lorem ipsum dolor sit amet, consectetur elit.", + }, + { + id: "item-2", + question: "How does EcoClean work?", + answer: "Lorem ipsum dolor sit amet consectetur elit.", + }, + { + id: "item-3", + question: "What are the key features of EcoClean?", + answer: "Lorem ipsum dolor sit amet, consectetur elit.", + }, + { + id: "item-4", + question: "Who can benefit from using EcoClean?", + answer: "Lorem ipsum dolor sit amet consectetur elit.", + }, + { + id: "item-5", + question: "What are the system requirements for EcoClean?", + answer: "Lorem ipsum dolor sit amet consectetur elit.", + }, + { + id: "item-6", + question: "How do I use EcoClean?", + answer: "Lorem ipsum dolor sit amet, consectetur elit.", + }, + { + id: "item-7", + question: "How do I store EcoClean?", + answer: "Lorem ipsum dolor sit amet, consectetur elit.", + }, + { + id: "item-8", + question: "How much does EcoClean cost?", + answer: "Lorem ipsum dolor sit amet, consectetur elit.", + }, + { + id: "item-9", + question: "Are there any discounts available?", + answer: "Lorem ipsum dolor sit amet, consectetur elit.", + }, +]; diff --git a/src/test/pricingpage/pricing.test.tsx b/src/test/pricingpage/pricing.test.tsx new file mode 100644 index 000000000..e8e232bcb --- /dev/null +++ b/src/test/pricingpage/pricing.test.tsx @@ -0,0 +1,38 @@ +import { fireEvent, render, screen } from "@testing-library/react"; + +import "@testing-library/jest-dom"; + +import Pricing from "~/app/(landing-routes)/pricing/page"; + +// + +describe("pricing Component", () => { + it("renders the pricing header", () => { + expect.assertions(1); + render(); + const pricingHeader = screen.getByTestId("pricing-header"); + expect(pricingHeader).toBeInTheDocument(); + }); + + it("toggles between monthly and annual plans", () => { + expect.assertions(2); + render(); + const monthlyToggle = screen.getByTestId("monthly-toggle"); + const annualToggle = screen.getByTestId("annual-toggle"); + + fireEvent.click(annualToggle); + const annualCard = screen.getByTestId("basic-card-annual"); + expect(annualCard).toBeInTheDocument(); + + fireEvent.click(monthlyToggle); + const monthlyCard = screen.getByTestId("basic-card-monthly"); + expect(monthlyCard).toBeInTheDocument(); + }); + + it("renders FAQ section", () => { + expect.assertions(1); + render(); + const faqSection = screen.getByTestId("faq-section"); + expect(faqSection).toBeInTheDocument(); + }); +}); From f91d699e8fe95714f93f295482fe5585cc64eb18 Mon Sep 17 00:00:00 2001 From: Ayodejioladimeji Date: Wed, 24 Jul 2024 15:10:14 +0100 Subject: [PATCH 3/4] fixed button import error --- src/components/layouts/careercard/CareerCard.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/layouts/careercard/CareerCard.tsx b/src/components/layouts/careercard/CareerCard.tsx index 74a556aa1..8acf15165 100644 --- a/src/components/layouts/careercard/CareerCard.tsx +++ b/src/components/layouts/careercard/CareerCard.tsx @@ -1,8 +1,9 @@ import { FC } from "react"; +import { Button } from "~/components/ui/button"; import { Card, CardContent, CardFooter } from "~/components/ui/card"; import { Skeleton } from "~/components/ui/skeleton"; -import CustomButton from "../Button/button"; + interface CareerCardProperties { isLoading: boolean; @@ -54,7 +55,7 @@ const CareerCard: FC = ({ {amount} /month - View Details + )} From cc7b6f51b31e3cddf11f872bd3efec6fa21e742a Mon Sep 17 00:00:00 2001 From: Ayodejioladimeji Date: Wed, 24 Jul 2024 15:16:16 +0100 Subject: [PATCH 4/4] fixed errors --- .../common/CareerCard/CareerCard.tsx | 3 +- .../layouts/careercard/CareerCard.tsx | 66 ------------------- src/components/layouts/careercard/index.tsx | 29 -------- 3 files changed, 2 insertions(+), 96 deletions(-) delete mode 100644 src/components/layouts/careercard/CareerCard.tsx delete mode 100644 src/components/layouts/careercard/index.tsx diff --git a/src/components/common/CareerCard/CareerCard.tsx b/src/components/common/CareerCard/CareerCard.tsx index 92a6aa0dd..a83bbe5c9 100644 --- a/src/components/common/CareerCard/CareerCard.tsx +++ b/src/components/common/CareerCard/CareerCard.tsx @@ -2,7 +2,8 @@ import { FC } from "react"; import { Card, CardContent, CardFooter } from "~/components/ui/card"; import { Skeleton } from "~/components/ui/skeleton"; -import CustomButton from "../Button/button"; +import CustomButton from "../button/button"; + interface CareerCardProperties { isLoading: boolean; diff --git a/src/components/layouts/careercard/CareerCard.tsx b/src/components/layouts/careercard/CareerCard.tsx deleted file mode 100644 index 8acf15165..000000000 --- a/src/components/layouts/careercard/CareerCard.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { FC } from "react"; -import { Button } from "~/components/ui/button"; - -import { Card, CardContent, CardFooter } from "~/components/ui/card"; -import { Skeleton } from "~/components/ui/skeleton"; - - -interface CareerCardProperties { - isLoading: boolean; - jobTitle?: string; - location?: string; - description?: string; - amount?: string; -} - -const CareerCard: FC = ({ - isLoading, - jobTitle, - location, - description, - amount, -}) => { - return ( - - - {isLoading ? ( -
- -
- - -
-
- ) : ( - <> -

{jobTitle}

-

{location}

-

{description}

- - )} -
- - - {isLoading ? ( - <> - - - - ) : ( - <> - - {amount} - /month - - - - )} - -
- ); -}; - -export default CareerCard; diff --git a/src/components/layouts/careercard/index.tsx b/src/components/layouts/careercard/index.tsx deleted file mode 100644 index 737247a3b..000000000 --- a/src/components/layouts/careercard/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client"; - -import { FC, useEffect, useState } from "react"; - -import CareerCard from "./CareerCard"; - -const CareerCardParent: FC = () => { - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - const timer = setTimeout(() => { - setIsLoading(false); - }, 2000); - - return () => clearTimeout(timer); - }, []); - - return ( - - ); -}; - -export default CareerCardParent;