Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

FEAT/HNG Add Logo team bulldozer #755

Merged
merged 10 commits into from
Jul 30, 2024
Binary file added public/images/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"use client";

import Image from "next/image";
import React, { useState } from "react";

const AddLogo: React.FC = () => {
const [selectedImage, setSelectedImage] = useState<
string | ArrayBuffer | undefined
>();

const handleImageChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setSelectedImage(reader.result ?? undefined);
};
reader.readAsDataURL(file);
}
};

return (
<div className="h-52 w-4/5 rounded-sm border bg-white p-4 shadow-md hover:border-orange-500">
<label className="flex flex-col items-center">
<div className="mb-4 flex h-44 w-48 cursor-pointer items-center justify-center bg-gray-50">
{selectedImage ? (
<Image
src={selectedImage as string}
alt="Selected"
className="h-full w-full object-contain"
width={192}
height={192}
/>
) : (
<span className="text-gray-400">Add your logo</span>
)}
</div>
<input
type="file"
accept="image/*"
onChange={handleImageChange}
className="hidden"
/>
</label>
</div>
);
};

export default AddLogo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from "react";

interface InputProperties {
label: string;
value: string;
onChange: (error: React.ChangeEvent<HTMLInputElement>) => void;
type?: string;
placeholder?: string;
}

const Input: React.FC<InputProperties> = ({
label,
value,
onChange,
type = "text",
placeholder,
}) => {
return (
<div className="mb-4">
<label className="mb-2 block text-sm font-bold text-gray-700">
{label}
</label>
<input
type={type}
value={value}
onChange={onChange}
placeholder={placeholder}
className="w-full appearance-none rounded border px-3 py-2 leading-tight text-gray-700 shadow focus:shadow-outline focus:outline-none"
/>
</div>
);
};

export default Input;
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"use client";

import React, { ChangeEvent, useState } from "react";

import Input from "./Input";

interface InputProperties {
label: string;
value: string;
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
placeholder: string;
}

interface ModalProperties {
inputs: InputProperties[];
buttonText?: string;
}

const Modal: React.FC<ModalProperties> = ({ inputs, buttonText = "Save" }) => {
const initialFormValues: { [key: string]: string } = {};
for (const input of inputs) {
initialFormValues[input.label] = "";
}

const [formValues, setFormValues] = useState<{ [key: string]: string }>(
initialFormValues,
);

const handleChange =
(label: string) => (event: ChangeEvent<HTMLInputElement>) => {
setFormValues((previousValues) => ({
...previousValues,
[label]: event.target.value,
}));
};

return (
<div className="inline-block transform overflow-hidden rounded-md bg-white px-4 pb-4 pt-5 text-left align-bottom shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6 sm:align-middle">
<div>
<div className="mt-3 sm:mt-5">
<div className="mt-2">
{inputs.map((input) => (
<Input
key={input.label}
label={input.label}
value={formValues[input.label] || ""}
onChange={handleChange(input.label)}
placeholder={input.placeholder}
/>
))}
</div>
</div>
</div>
<div className="mt-5 flex sm:mt-6">
<button className="inline-flex justify-center rounded-md border border-transparent bg-orange-500 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-orange-600 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 sm:text-sm">
{buttonText}
</button>
</div>
</div>
);
};

export default Modal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"use client";

import { LucideProps } from "lucide-react";
import Link from "next/link";
import { FC, ForwardRefExoticComponent, useState } from "react";

import { Breadcrumb } from "~/components/common/breadcrumb";
import PageHeader from "../../../_components/page-header";
import Pagination from "../../../_components/pagination";
import TemplateCard from "../../../_components/template-card/TemplateCard";
import PreviewCard from "../preview-card";

interface IOption {
data: {
title: string;
description: string;
icon: ForwardRefExoticComponent<
Omit<LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>
>;
link: string;
};
}

export const Options: FC<IOption> = ({ data }) => {
return (
<Link
data-testid="email-home-card"
href={data.link}
className="flex w-full max-w-[310px] cursor-pointer items-center justify-between gap-5 rounded-[8px] border-[1px] border-[#CBD5E1B2] px-5 py-4 transition-all duration-300 hover:border-primary"
>
<div className="flex w-6 items-center justify-center">
<data.icon
className="h-6 w-6 text-neutral-dark-2"
size={24}
role="option-icon"
/>
</div>
<div>
<h3 className="mb-2 text-sm font-semibold text-neutral-dark-2">
{data.title}
</h3>
<p className="mb-2 text-sm text-neutral-dark-2">{data.description}</p>
</div>
</Link>
);
};
const ManageTemplate = () => {
const isloading: boolean = false;
const data = 100;
const [togglePreview, setTogglePreview] = useState<boolean>(false);
const [currentPage, setCurrentPage] = useState<number>(1);
const totalPage = Math.ceil(data / 10);
return (
<div>
<section className="mb-8">
<PageHeader
title="Manage Your Template"
description="Explore your library of sent templates."
/>
<Breadcrumb />
</section>
<div
className={`${togglePreview ? "grid grid-cols-1 justify-items-center gap-6 lg:grid-cols-[1fr_447px]" : "block"} `}
>
<section className="w-full justify-items-center overflow-hidden rounded-[19px] border-[1px] border-border">
<div className="grid min-h-[700px] grid-rows-[1fr_auto]">
<div>
<TemplateCard
togglePreview={togglePreview}
setTogglePreview={setTogglePreview}
/>
</div>
<Pagination
isloading={isloading}
totalPage={totalPage}
currentPage={currentPage}
setCurrentPage={setCurrentPage}
/>
</div>
</section>
{togglePreview && <PreviewCard />}
</div>
</div>
);
};

export default ManageTemplate;
Loading