Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…remix into HNG-58-admin-product-list-page
  • Loading branch information
jerahmeel200 committed Jul 23, 2024
2 parents 481cf95 + 0425e2a commit 8de20e7
Show file tree
Hide file tree
Showing 75 changed files with 3,682 additions and 151 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"source.fixAll.eslint": "always"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "vscode.typescript-language-features"
},
}
125 changes: 125 additions & 0 deletions app/components/BreadCrumbs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { Slot } from "@radix-ui/react-slot";
import { ChevronRight, MoreHorizontal } from "lucide-react";
import {
forwardRef,
type ComponentProps,
type ComponentPropsWithoutRef,
type ReactNode,
} from "react";

import { cn } from "~/lib/utils/cn";

const Breadcrumb = forwardRef<
HTMLElement,
ComponentPropsWithoutRef<"nav"> & {
separator?: ReactNode;
}
>(({ ...properties }, reference) => (
<nav ref={reference} aria-label="breadcrumb" {...properties} />
));
Breadcrumb.displayName = "Breadcrumb";

const BreadcrumbList = forwardRef<
HTMLOListElement,
ComponentPropsWithoutRef<"ol">
>(({ className, ...properties }, reference) => (
<ol
ref={reference}
className={cn(
"flex flex-wrap items-center gap-1.5 break-words text-xs text-foreground sm:gap-3",
className,
)}
{...properties}
/>
));
BreadcrumbList.displayName = "BreadcrumbList";

const BreadcrumbItem = forwardRef<
HTMLLIElement,
ComponentPropsWithoutRef<"li">
>(({ className, ...properties }, reference) => (
<li
ref={reference}
className={cn("inline-flex items-center gap-1.5", className)}
{...properties}
/>
));
BreadcrumbItem.displayName = "BreadcrumbItem";

const BreadcrumbLink = forwardRef<
HTMLAnchorElement,
ComponentPropsWithoutRef<"a"> & {
asChild?: boolean;
}
>(({ asChild, className, ...properties }, reference) => {
const Comp = asChild ? Slot : "a";

return (
<Comp
ref={reference}
className={cn(
"text-breadcrumb-foreground hover:text-neutral-dark-2 capitalize transition-colors",
className,
)}
{...properties}
/>
);
});
BreadcrumbLink.displayName = "BreadcrumbLink";

const BreadcrumbPage = forwardRef<
HTMLSpanElement,
ComponentPropsWithoutRef<"span">
>(({ className, ...properties }, reference) => (
<span
ref={reference}
role="link"
aria-disabled="true"
aria-current="page"
className={cn("text-breadcrumb-page/50 font-normal capitalize", className)}
{...properties}
/>
));
BreadcrumbPage.displayName = "BreadcrumbPage";

const BreadcrumbSeparator = ({
children,
className,
...properties
}: ComponentProps<"li">) => (
<li
role="presentation"
aria-hidden="true"
className={cn("text-breadcrumb-page [&>svg]:size-3.5", className)}
{...properties}
>
{children ?? <ChevronRight />}
</li>
);
BreadcrumbSeparator.displayName = "BreadcrumbSeparator";

const BreadcrumbEllipsis = ({
className,
...properties
}: ComponentProps<"span">) => (
<span
role="presentation"
aria-hidden="true"
className={cn("flex h-9 w-9 items-center justify-center", className)}
{...properties}
>
<MoreHorizontal className="h-4 w-4" />
<span className="sr-only">More</span>
</span>
);
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis";

export {
Breadcrumb,
BreadcrumbList,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbPage,
BreadcrumbSeparator,
BreadcrumbEllipsis,
};
106 changes: 106 additions & 0 deletions app/components/CreateRoleFormModal/CreateRoleForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Form } from "@remix-run/react";
import { FC, useState } from "react";

import CreateRoleModal from "./CreateRoleModal";

interface CreateRoleFormProperties {
isOpen: boolean;
onClose: () => void;
}

const CreateRoleForm: FC<CreateRoleFormProperties> = ({ isOpen, onClose }) => {
const [roleName, setRoleName] = useState("");
const [roleDescription, setRoleDescription] = useState("");

const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();

onClose();
};

return (
<CreateRoleModal isOpen={isOpen}>
<div className="p-6">
<div className="mb-4 flex items-center justify-between">
<h2 className="text-xl font-semibold">Create Role</h2>
<button
onClick={onClose}
className="text-gray-500 hover:text-gray-700"
>
<svg
className="h-6 w-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<p className="mb-4 text-sm text-gray-600">
Define customized responsibilities for collaborative success.
</p>
<Form method="post" onSubmit={handleSubmit}>
<div className="mb-4">
<label
htmlFor="roleName"
className="mb-1 block text-sm font-bold text-[#0A0A0A]"
>
Name of role
</label>
<input
type="text"
id="roleName"
name="roleName"
placeholder="e.g: IT Staff"
value={roleName}
onChange={(event) => setRoleName(event.target.value)}
className="w-[50%] rounded-md border border-border p-2 text-sm font-normal text-[#525252]"
required
/>
</div>
<div className="mb-6">
<label
htmlFor="roleDescription"
className="mb-1 block border-border text-sm font-bold text-[#0A0A0A] outline-border"
>
Role description
</label>
<textarea
id="roleDescription"
name="roleDescription"
placeholder="Describe role"
value={roleDescription}
onChange={(event) => setRoleDescription(event.target.value)}
className="h-24 w-full resize-none rounded-md border border-gray-300 p-2 text-sm font-normal text-[#525252]"
required
/>
</div>
<div className="flex justify-end space-x-2">
<button
type="button"
onClick={onClose}
className="rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50"
>
Cancel
</button>
<button
type="submit"
className="rounded-md bg-orange-500 px-4 py-2 text-sm font-medium text-white hover:bg-orange-600"
>
Create Role
</button>
</div>
</Form>
</div>
</CreateRoleModal>
);
};

export default CreateRoleForm;
23 changes: 23 additions & 0 deletions app/components/CreateRoleFormModal/CreateRoleModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { FC, ReactNode } from "react";

interface CreateRoleModalProperties {
isOpen: boolean;
children: ReactNode;
}

const CreateRoleModal: FC<CreateRoleModalProperties> = ({
isOpen,
children,
}) => {
if (!isOpen) return;

return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50">
<div className="mx-4 w-full max-w-md rounded-lg bg-white shadow-lg">
{children}
</div>
</div>
);
};

export default CreateRoleModal;
42 changes: 42 additions & 0 deletions app/components/InvoiceEmail/DetailTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Column, Heading, Row, Section, Text } from "@react-email/components";

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

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

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

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

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

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

0 comments on commit 8de20e7

Please sign in to comment.