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: add alert, form button from shadcn and create new template with… #374

Merged
merged 9 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions app/components/PaymentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ const PaymentForm = (properties: PaymentFormProperties) => {
name="radioGroup"
id=""
value={"Debit/Credit Card"}
className="h-5 w-5 border bg-white checked:border-primary checked:accent-primary"
className="h-5 w-5 border accent-primary checked:bg-transparent"
/>
<label htmlFor="">Debit/Credit Card</label>
<label htmlFor="" className="text-gray-600">
Debit/Credit Card
</label>
</div>
<hr />
<div className="flex gap-2 p-3">
Expand All @@ -70,7 +72,9 @@ const PaymentForm = (properties: PaymentFormProperties) => {
value={"Paypal"}
className="h-5 w-5 border accent-primary checked:bg-white"
/>
<label htmlFor="">Paypal</label>
<label htmlFor="" className="text-gray-600">
Paypal
</label>
</div>
</div>
<div className="mb-4">
Expand Down Expand Up @@ -158,6 +162,13 @@ const PaymentForm = (properties: PaymentFormProperties) => {
</div>
<div>
<Button className="m-auto w-full">Confirm and Pay</Button>
<small className="text-gray-800">
Your subscription will renew automatically every month as one payment
of $800. <br />
Cancel it anytime from your subscription settings. By clicking
&quot;Confirm and Pay&quot;, you agree to the
<span className="text-primary"> Terms and Conditions</span>
</small>
</div>
</form>
);
Expand Down
7 changes: 0 additions & 7 deletions app/components/passwordSetting/PasswordSettingForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ export default function PasswordSetting() {
const watchForConfirmPassword = watch("confirmPassword", "");
const watchForCurrentPassword = watch("currentPassword");

const maskedNewPassword = "*".repeat(watchForNewPassword.length);
const maskedConfirmPassword = "*".repeat(watchForConfirmPassword.length);
const maskedCurrentPassword = "*".repeat(watchForCurrentPassword.length);

//Toggle submit diasbled to true if all field have value more than 8
const isFormDisabled =
watchForNewPassword.length < 8 ||
Expand Down Expand Up @@ -128,7 +124,6 @@ export default function PasswordSetting() {
required: true,
})}
type={inputType}
value={maskedCurrentPassword}
/>
<Button
className="absolute right-[1em] bg-transparent text-[#939393] hover:bg-transparent"
Expand Down Expand Up @@ -162,7 +157,6 @@ export default function PasswordSetting() {
{...register("newPassword", {
required: true,
})}
value={maskedNewPassword}
/>
<Button
className="absolute right-[1em] bg-transparent text-[#939393] hover:bg-transparent"
Expand Down Expand Up @@ -231,7 +225,6 @@ export default function PasswordSetting() {
required: true,
})}
type={inputType}
value={maskedConfirmPassword}
/>
<Button
className="absolute right-[1em] bg-transparent text-[#939393] hover:bg-transparent"
Expand Down
58 changes: 58 additions & 0 deletions app/components/ui/alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { cn } from "app/lib/utils/cn";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";

const alertVariants = cva(
"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
{
variants: {
variant: {
default: "bg-background text-foreground",
destructive:
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
},
},
defaultVariants: {
variant: "default",
},
},
);

const Alert = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
>(({ className, variant, ...properties }, reference) => (
<div
ref={reference}
role="alert"
className={cn(alertVariants({ variant }), className)}
{...properties}
/>
));
Alert.displayName = "Alert";

const AlertTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...properties }, reference) => (
<h5
ref={reference}
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
{...properties}
/>
));
AlertTitle.displayName = "AlertTitle";

const AlertDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...properties }, reference) => (
<div
ref={reference}
className={cn("text-sm [&_p]:leading-relaxed", className)}
{...properties}
/>
));
AlertDescription.displayName = "AlertDescription";

export { Alert, AlertTitle, AlertDescription };
180 changes: 180 additions & 0 deletions app/components/ui/form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
"use client";

import * as LabelPrimitive from "@radix-ui/react-label";
import { Slot } from "@radix-ui/react-slot";
import { Label } from "app/components/ui/label";
import { cn } from "app/lib/utils/cn";
import * as React from "react";
import {
Controller,
ControllerProps,
FieldPath,
FieldValues,
FormProvider,
useFormContext,
} from "react-hook-form";

const Form = FormProvider;

type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = {
name: TName;
};

const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue,
);

const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
...properties
}: ControllerProps<TFieldValues, TName>) => {
return (
<FormFieldContext.Provider value={{ name: properties.name }}>
<Controller {...properties} />
</FormFieldContext.Provider>
);
};

const useFormField = () => {
const fieldContext = React.useContext(FormFieldContext);
const itemContext = React.useContext(FormItemContext);
const { getFieldState, formState } = useFormContext();

const fieldState = getFieldState(fieldContext.name, formState);

if (!fieldContext) {
throw new Error("useFormField should be used within <FormField>");
}

const { id } = itemContext;

return {
id,
name: fieldContext.name,
formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`,
...fieldState,
};
};

type FormItemContextValue = {
id: string;
};

const FormItemContext = React.createContext<FormItemContextValue>(
{} as FormItemContextValue,
);

const FormItem = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...properties }, reference) => {
const id = React.useId();

return (
<FormItemContext.Provider value={{ id }}>
<div
ref={reference}
className={cn("space-y-2", className)}
{...properties}
/>
</FormItemContext.Provider>
);
});
FormItem.displayName = "FormItem";

const FormLabel = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
>(({ className, ...properties }, reference) => {
const { error, formItemId } = useFormField();

return (
<Label
ref={reference}
className={cn(error && "text-destructive", className)}
htmlFor={formItemId}
{...properties}
/>
);
});
FormLabel.displayName = "FormLabel";

const FormControl = React.forwardRef<
React.ElementRef<typeof Slot>,
React.ComponentPropsWithoutRef<typeof Slot>
>(({ ...properties }, reference) => {
const { error, formItemId, formDescriptionId, formMessageId } =
useFormField();

return (
<Slot
ref={reference}
id={formItemId}
aria-describedby={
error ? `${formDescriptionId} ${formMessageId}` : `${formDescriptionId}`
}
aria-invalid={!!error}
{...properties}
/>
);
});
FormControl.displayName = "FormControl";

const FormDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...properties }, reference) => {
const { formDescriptionId } = useFormField();

return (
<p
ref={reference}
id={formDescriptionId}
className={cn("text-sm text-muted-foreground", className)}
{...properties}
/>
);
});
FormDescription.displayName = "FormDescription";

const FormMessage = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, children, ...properties }, reference) => {
const { error, formMessageId } = useFormField();
const body = error ? String(error?.message) : children;

if (!body) {
return;
}

return (
<p
ref={reference}
id={formMessageId}
className={cn("text-sm font-medium text-destructive", className)}
{...properties}
>
{body}
</p>
);
});
FormMessage.displayName = "FormMessage";

export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
};
2 changes: 0 additions & 2 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
} from "@remix-run/react";
import type { ReactNode } from "react";

import { AdminSideNavBar } from "./components/SuperAdminSideBar/SuperAdminSideNavBar";
import styles from "./styles/global.css?url";

export const links: LinksFunction = () => [
Expand All @@ -28,7 +27,6 @@ export function Layout({ children }: { children: ReactNode }) {
</head>
<body>
<div className="flex">
<AdminSideNavBar />
<main className="flex-1">{children}</main>,
<ScrollRestoration />
<Scripts />
Expand Down
4 changes: 3 additions & 1 deletion app/routes/pricing.payment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useState } from "react";
import DetailsForm from "~/components/DetailsForm";
import PaymentForm from "~/components/PaymentForm";
import PricingPaymentBreadCrumb from "~/components/PricingPaymentBreadCrumb";
import Footer from "~/email/templates/_components/Footer";

const Payment = () => {
const [showSecondForm, setShowSecondForm] = useState(false);
Expand All @@ -16,7 +17,7 @@ const Payment = () => {
<div className="mx-auto flex w-10/12 flex-col gap-6 py-[5%] md:flex-row md:justify-between">
<div className="w-full">
<h2 className="mb-4">Order Details</h2>
<div className="w-full rounded bg-[#fff] px-6 py-3">
<div className="w-full rounded bg-[#ffffff] px-6 py-3">
<h2 className="text-lg font-semibold">Basic Plan</h2>
<div className="flex justify-between leading-loose md:w-full">
<span className="leading-loose">Monthly Subscription</span>
Expand All @@ -43,6 +44,7 @@ const Payment = () => {
</div>
</div>
</div>
<Footer />
</div>
);
};
Expand Down