Skip to content

Commit

Permalink
Merge pull request #35 from hngprojects/step-one-form
Browse files Browse the repository at this point in the history
feat: Added slick-carousel dependency and fixed hydration error
  • Loading branch information
Joshuafolorunsho authored Mar 6, 2025
2 parents 9f100a7 + eedfb47 commit 4cd8dcd
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 78 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"react-dom": "^19.0.0",
"react-hook-form": "^7.54.2",
"react-slick": "^0.30.3",
"slick-carousel": "^1.8.1",
"sonner": "^2.0.1",
"tailwind-merge": "^3.0.2",
"tailwindcss-animate": "^1.0.7",
Expand Down
17 changes: 17 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 45 additions & 43 deletions src/app/ad-form/_components/image-ad-form.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"use client";
import React from "react";
import dynamic from "next/dynamic";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useRouter } from "next/navigation";
import {
Select,
SelectContent,
Expand All @@ -23,7 +23,6 @@ import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import CustomMultiSelect from "@/components/ui/multi-select";
import {
demographicsOptions,
regionOptions,
Expand All @@ -32,12 +31,18 @@ import {
ageGroupOptions,
} from "@/app/constants/step-one-form-options";
import { ImageAdSchema } from "@/schemas/ad-schema";
import Image from "next/image";
import Link from "next/link";
const DynamicMultiSelect = dynamic(
() => import("@/components/ui/multi-select"),
{
ssr: false,
}
);

type FormData = z.infer<typeof ImageAdSchema>;

export const ImageAdForm = () => {
const router = useRouter();

const form = useForm<FormData>({
resolver: zodResolver(ImageAdSchema),
Expand All @@ -57,57 +62,54 @@ export const ImageAdForm = () => {
console.log("Image Ad Data:", data);
};

const handleBack = () => {
router.push("/ad-selector");
};

return (
<div className="min-h-full bg-[#F9FAFB] p-6 py-18 flex justify-center items-center">
<Card className="w-full max-w-[890px]">
<CardContent className="p-14">
<div className="mb-8">
<Button
variant="ghost"
onClick={handleBack}
<Link
href="/ad-type"
className="flex items-center text-gray-600 hover:text-gray-800 cursor-pointer p-0"
>
<img src="/arrow-left.svg" alt="Back" className="w-5 h-5 mr-2" />
<Image
src="/arrow-left.svg"
alt="Back"
className="w-5 h-5 mr-2"
width={10}
height={10}
/>
<span>Back</span>
</Button>
</Link>
</div>

<CardHeader className="p-0 mb-6 text-center">
<CardTitle className="text-2xl font-bold">
Let&apos;s set up your Ad
</CardTitle>
<p className="text-gray-500 mt-2">
Fill in the details below, then AI generates your ad instantly.
</p>
</CardHeader>
<CardTitle className="text-2xl font-bold">
Let&apos;s set up your Ad
</CardTitle>
<p className="text-gray-500 mt-2">
Fill in the details below, then AI generates your ad instantly.
</p>
</CardHeader>

<div className="mb-8">

<div className="flex justify-around items-center">

<div className="text-center">
<p className="text-sm text-black font-medium">STEP 1</p>
<p className="text-xs mt-1 text-gray-700">Set Ad goals</p>
</div>

<div className="text-center">
<p className="text-sm text-gray-400 font-medium">STEP 2</p>
<p className="text-xs mt-1 text-gray-400">Preview</p>
</div>
</div>
<div className="mb-8">
<div className="flex justify-around items-center">
<div className="text-center">
<p className="text-sm text-black font-medium">STEP 1</p>
<p className="text-xs mt-1 text-gray-700">Set Ad goals</p>
</div>

<div className="text-center">
<p className="text-sm text-gray-400 font-medium">STEP 2</p>
<p className="text-xs mt-1 text-gray-400">Preview</p>
</div>
</div>


<div className="relative w-full h-2 bg-white-200 rounded-full mt-4 mb-4">

<div className="absolute left-0 h-2 bg-[#1467C5] rounded-l-full w-[48%]"></div>

<div className="absolute right-0 h-2 bg-gray-300 rounded-r-full w-[48%]"></div>
</div>
</div>
<div className="relative w-full h-2 bg-white-200 rounded-full mt-4 mb-4">
<div className="absolute left-0 h-2 bg-[#1467C5] rounded-l-full w-[48%]"></div>

<div className="absolute right-0 h-2 bg-gray-300 rounded-r-full w-[48%]"></div>
</div>
</div>

<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
Expand Down Expand Up @@ -198,7 +200,7 @@ export const ImageAdForm = () => {
Target Age Group
</FormLabel>
<FormControl>
<CustomMultiSelect
<DynamicMultiSelect
options={ageGroupOptions}
selected={field.value || []}
onChange={field.onChange}
Expand Down Expand Up @@ -308,7 +310,7 @@ export const ImageAdForm = () => {
disabled={!form.formState.isValid}
className={`px-6 py-3 rounded-md transition-colors ${
form.formState.isValid
? "bg-[#B800B8] text-white hover:bg-[#960096]"
? "bg-[#B800B8] text-white hover:bg-[#960096] cursor-pointer"
: "bg-gray-300 text-gray-500 cursor-not-allowed"
}`}
>
Expand Down
112 changes: 93 additions & 19 deletions src/app/ad-type/ad-type-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import React, { useState } from "react";
import Image from "next/image";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";

const AdSelectorPage = () => {
const router = useRouter();
Expand All @@ -23,45 +24,118 @@ const AdSelectorPage = () => {
}
};

const handleBack = () => {
router.push("/ad-type");
};

return (
<div className="min-h-screen bg-[#F9FAFB] flex justify-center items-center p-6">
<div className="w-full max-w-lg md:max-w-3xl bg-white border rounded-md p-6 md:p-14">
<div className="mb-6">
<button
onClick={handleBack}
className="flex items-center text-gray-600 hover:text-gray-800"
<Link
href="/"
className="flex items-center text-gray-600 hover:text-gray-800 cursor-pointer p-0"
>
<img src="/arrow-left.svg" alt="Back" className="w-5 h-5 mr-2" />
<Image
src="/arrow-left.svg"
alt="Back"
className="w-5 h-5 mr-2"
width={10}
height={10}
/>
<span>Back</span>
</button>
</Link>
</div>

<h2 className="text-xl md:text-2xl font-bold mb-6">Select Ad Type</h2>

<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">

<div
className={`border p-6 rounded-lg cursor-pointer transition-all flex flex-col ${
className={`border p-6 rounded-lg cursor-pointer transition-all flex justify-between ${
selectedAdType === "image"
? "border-[#B800B8] bg-[#F3E8F3]"
: "border-gray-300 hover:border-[#B800B8]/50"
}`}
onClick={() => handleAdTypeSelect("image")}
>
<Image src="/Image.svg" alt="image svg" width={30} height={30} />
<div className="mt-4">
<h3 className="font-semibold text-base">Image Ad</h3>
<p className="text-sm text-gray-600">
Static image ads for social media, websites, and print.
</p>
<div className="flex flex-col items-start justify-center mb-4 ">
<Image
src="/image-icon.svg"
alt="image svg"
className="max-w-full max-h-full object-contain"
quality={100}
width={20}
height={20}
/>
<div className="mt-4">
<h3 className="font-semibold text-base mb-1">Image Ad</h3>
<p className="text-sm text-gray-600 max-w-[250px]">
Static image ads for social media, websites, and print
</p>
</div>
</div>

<div
className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
selectedAdType === "image"
? "border-[#B800B8] bg-[#B800B8]"
: "border-gray-300"
}`}
>
{selectedAdType === "image" && (
<Image
src="/check.svg"
alt="image svg"
className="max-w-full max-h-full object-contain"
quality={100}
width={20}
height={20}
/>
)}
</div>
</div>
{/*
<div
className={`border-1 w-[371px] p-6 rounded-lg cursor-pointer transition-all flex items-start justify-between ${
selectedAdType === "image"
? "border-[#B800B8] bg-[#F3E8F3]"
: "border-gray-300 hover:border-[#B800B8]/50"
}`}
onClick={() => handleAdTypeSelect("image")}
>
<div className="flex flex-col items-start justify-center mb-4 ">
<Image
src="/image-icon.svg"
alt="image svg"
className="max-w-full max-h-full object-contain"
quality={100}
width={20}
height={20}
/>
<div className="mt-4">
<h3 className="font-semibold text-base mb-1">Image Ad</h3>
<p className="text-sm text-gray-600 max-w-[250px]">
Static image ads for social media, websites, and print
</p>
</div>
</div>
<div
className={`w-3 h-3 rounded-full border-2 flex items-center justify-center ${
selectedAdType === "image"
? "border-[#B800B8] bg-[#B800B8]"
: "border-gray-300"
}`}
>
{selectedAdType === "image" && (
<Image
src="/check.svg"
alt="image svg"
className="max-w-full max-h-full object-contain"
quality={100}
width={20}
height={20}
/>
)}
</div>
</div> */}


<div className="border p-6 rounded-lg flex flex-col border-gray-300 bg-gray-100 opacity-50 cursor-not-allowed">
<Image src="/video.svg" alt="Video svg" width={30} height={30} />
<div className="mt-4 flex flex-wrap items-center gap-2">
Expand All @@ -78,7 +152,7 @@ const AdSelectorPage = () => {

<div className="flex justify-end">
<button
className={`px-6 py-3 rounded-md transition-colors ${
className={`px-6 py-3 rounded-md transition-colors cursor-pointer ${
selectedAdType
? "bg-[#B800B8] text-white hover:bg-[#960096]"
: "bg-gray-300 text-gray-500 cursor-not-allowed"
Expand Down
16 changes: 2 additions & 14 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Manrope } from "next/font/google";

import { TopProgressBarProvider } from "@/lib/nprogress/top-progress-bar-provider";
import QueryProvider from "@/lib/react-query/query-provider";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";

import "./globals.css";

Expand All @@ -28,20 +30,6 @@ export default function RootLayout({
}>) {
return (
<html lang="en" className={clsx(manrope.variable)}>
<head>
<link
rel="stylesheet"
type="text/css"
charSet="UTF-8"
href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css"
/>
<link
rel="stylesheet"
type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css"
/>
</head>

<body className="font-nunito bg-[#F9FAFB]">
<SonnerToaster />
<QueryProvider>
Expand Down
Loading

0 comments on commit 4cd8dcd

Please sign in to comment.