Merge branch 'main' into hongpo/update-question-filter

pull/409/head
hpkoh 3 years ago
commit 3847b0569d

@ -1,7 +1,7 @@
import type { ProductNavigationItems } from '~/components/global/ProductNavigation'; import type { ProductNavigationItems } from '~/components/global/ProductNavigation';
const navigation: ProductNavigationItems = [ const navigation: ProductNavigationItems = [
{ href: '/offers/home', name: 'Home' }, { href: '/offers/browse', name: 'Browse' },
{ href: '/offers/submit', name: 'Analyse your offers' }, { href: '/offers/submit', name: 'Analyse your offers' },
]; ];

@ -1,5 +1,7 @@
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { HOME_URL } from '~/components/offers/types';
type LeftTextCardProps = Readonly<{ type LeftTextCardProps = Readonly<{
description: string; description: string;
icon: ReactNode; icon: ReactNode;
@ -8,7 +10,6 @@ type LeftTextCardProps = Readonly<{
title: string; title: string;
}>; }>;
const baseUrl = '/offers/home';
export default function LeftTextCard({ export default function LeftTextCard({
description, description,
icon, icon,
@ -21,7 +22,7 @@ export default function LeftTextCard({
<div className="mx-auto max-w-xl px-4 sm:px-6 lg:mx-0 lg:max-w-none lg:py-16 lg:px-0"> <div className="mx-auto max-w-xl px-4 sm:px-6 lg:mx-0 lg:max-w-none lg:py-16 lg:px-0">
<div> <div>
<div> <div>
<span className="flex h-12 w-12 items-center justify-center rounded-md bg-gradient-to-r from-purple-600 to-indigo-600"> <span className="to-primary-500 flex h-12 w-12 items-center justify-center rounded-md bg-gradient-to-r from-purple-600">
{icon} {icon}
</span> </span>
</div> </div>
@ -32,8 +33,8 @@ export default function LeftTextCard({
<p className="mt-4 text-lg text-gray-500">{description}</p> <p className="mt-4 text-lg text-gray-500">{description}</p>
<div className="mt-6"> <div className="mt-6">
<a <a
className="inline-flex rounded-md border border-transparent bg-gradient-to-r from-purple-600 to-indigo-600 bg-origin-border px-4 py-2 text-base font-medium text-white shadow-sm hover:from-purple-700 hover:to-indigo-700" className="to-primary-500 inline-flex rounded-md border border-transparent bg-gradient-to-r from-purple-600 bg-origin-border px-4 py-2 text-base font-medium text-white shadow-sm hover:from-purple-700 hover:to-indigo-700"
href={baseUrl}> href={HOME_URL}>
Get started Get started
</a> </a>
</div> </div>

@ -1,5 +1,7 @@
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { HOME_URL } from '~/components/offers/types';
type RightTextCarddProps = Readonly<{ type RightTextCarddProps = Readonly<{
description: string; description: string;
icon: ReactNode; icon: ReactNode;
@ -8,7 +10,6 @@ type RightTextCarddProps = Readonly<{
title: string; title: string;
}>; }>;
const baseUrl = '/offers/home';
export default function RightTextCard({ export default function RightTextCard({
description, description,
icon, icon,
@ -21,7 +22,7 @@ export default function RightTextCard({
<div className="mx-auto max-w-xl px-4 sm:px-6 lg:col-start-2 lg:mx-0 lg:max-w-none lg:py-32 lg:px-0"> <div className="mx-auto max-w-xl px-4 sm:px-6 lg:col-start-2 lg:mx-0 lg:max-w-none lg:py-32 lg:px-0">
<div> <div>
<div> <div>
<span className="flex h-12 w-12 items-center justify-center rounded-md bg-gradient-to-r from-purple-600 to-indigo-600"> <span className="to-primary-500 flex h-12 w-12 items-center justify-center rounded-md bg-gradient-to-r from-purple-600">
{icon} {icon}
</span> </span>
</div> </div>
@ -32,8 +33,8 @@ export default function RightTextCard({
<p className="mt-4 text-lg text-gray-500">{description}</p> <p className="mt-4 text-lg text-gray-500">{description}</p>
<div className="mt-6"> <div className="mt-6">
<a <a
className="inline-flex rounded-md border border-transparent bg-gradient-to-r from-purple-600 to-indigo-600 bg-origin-border px-4 py-2 text-base font-medium text-white shadow-sm hover:from-purple-700 hover:to-indigo-700" className="to-primary-500 inline-flex rounded-md border border-transparent bg-gradient-to-r from-purple-600 bg-origin-border px-4 py-2 text-base font-medium text-white shadow-sm hover:from-purple-700 hover:to-indigo-700"
href={baseUrl}> href={HOME_URL}>
Get started Get started
</a> </a>
</div> </div>

@ -175,36 +175,7 @@ export default function ProfileComments({
) : ( ) : (
<div>Please log in before commenting on this profile.</div> <div>Please log in before commenting on this profile.</div>
)} )}
<div> <div className="h-full overflow-y-auto">
<TextArea
label={`Comment as ${
isEditable ? profileName : session?.user?.name ?? 'anonymous'
}`}
placeholder="Type your comment here"
value={currentReply}
onChange={(value) => setCurrentReply(value)}
/>
<div className="mt-2 flex w-full justify-end">
<div className="w-fit">
<Button
disabled={
commentsQuery.isLoading ||
!currentReply.length ||
createCommentMutation.isLoading
}
display="block"
isLabelHidden={false}
isLoading={createCommentMutation.isLoading}
label="Comment"
size="sm"
variant="primary"
onClick={() => handleComment(currentReply)}
/>
</div>
</div>
<HorizontalDivider />
</div>
<div className="h-full overflow-y-scroll">
<div className="h-content mb-96 w-full"> <div className="h-content mb-96 w-full">
{replies?.map((reply: Reply) => ( {replies?.map((reply: Reply) => (
<ExpandableCommentCard <ExpandableCommentCard

@ -2,6 +2,8 @@ import type { JobType } from '@prisma/client';
import type { MonthYear } from '~/components/shared/MonthYearPicker'; import type { MonthYear } from '~/components/shared/MonthYearPicker';
export const HOME_URL = '/offers/browse';
/* /*
* Offer Profile * Offer Profile
*/ */

@ -10,26 +10,26 @@ import {
import LeftTextCard from '~/components/offers/landing/LeftTextCard'; import LeftTextCard from '~/components/offers/landing/LeftTextCard';
import RightTextCard from '~/components/offers/landing/RightTextCard'; import RightTextCard from '~/components/offers/landing/RightTextCard';
const baseUrl = '/offers/home'; import { HOME_URL } from '~/components/offers/types';
const features = [ const features = [
{ {
description: description:
'Name of the profile creator is stricly anonymous by using randomly generated names.', 'Profile names are randomly generated to keep your offers strictly anonymous.',
icon: UsersIcon, icon: UsersIcon,
name: 'Anonymisd Profile Name', name: 'Anonymized Profile Name',
}, },
{ {
description: description:
' Only people with the edit link can edit that profile. Share profiles to others using public link without giving edit permission.', 'Only users with the edit link can edit that profile. Share profiles to others using a public link without giving edit permission.',
icon: ShareIcon, icon: ShareIcon,
name: 'Edit Link v.s. Public Link', name: 'Edit Link v.s. Public Link',
}, },
{ {
description: description:
"Offer profiles will not be automatically saved under creator's account in database unless explicit permission is given.", "Offer profiles will not be automatically saved under creators' account in our database unless explicit permission is given.",
icon: BookmarkSquareIcon, icon: BookmarkSquareIcon,
name: 'No Auto-Save to User Account', name: 'Save with Permission',
}, },
]; ];
@ -79,29 +79,29 @@ const footerNavigation = {
export default function LandingPage() { export default function LandingPage() {
return ( return (
<div className="overflow-y-auto bg-white"> <div className="mx-auto w-full overflow-y-auto bg-white">
<main> <main>
{/* Hero section */} {/* Hero section */}
<div className="relative h-full"> <div className="relative h-full">
<div className="relative px-4 py-16 sm:px-6 sm:py-24 lg:py-32 lg:px-8"> <div className="relative px-4 py-16 sm:px-6 sm:py-24 lg:py-32 lg:px-8">
<h1 className="text-center text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl"> <h1 className="text-center text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl">
<span className="block">Choosing offers made easier</span> <span>Choosing offers </span>
<span className="from-primary-600 -mb-1 block bg-gradient-to-r to-purple-500 bg-clip-text pb-1 text-transparent"> <span className="from-primary-600 -mb-1 mr-2 bg-gradient-to-r to-purple-500 bg-clip-text pb-1 pr-4 italic text-transparent">
using profiles behind offers. made easier
</span> </span>
</h1> </h1>
<p className="text-primary-600 mx-auto mt-6 max-w-lg text-center text-xl sm:max-w-3xl"> <p className="mx-auto mt-6 max-w-lg text-center text-xl sm:max-w-3xl">
Analyse your offers using profiles from fellow software engineers. Analyze your offers using profiles from fellow software engineers.
</p> </p>
<div className="mx-auto mt-10 max-w-sm sm:flex sm:max-w-none sm:justify-center"> <div className="mx-auto mt-10 max-w-sm sm:flex sm:max-w-none sm:justify-center">
<div className="space-y-4 sm:mx-auto sm:inline-grid sm:grid-cols-2 sm:gap-5 sm:space-y-0"> <div className="space-y-4 sm:mx-auto sm:inline-grid sm:grid-cols-2 sm:gap-5 sm:space-y-0">
<a <a
className="border-grey-600 flex items-center justify-center rounded-md border bg-white bg-white px-4 py-3 text-base font-medium text-indigo-700 shadow-sm hover:bg-indigo-50 sm:px-8" className="border-grey-600 flex items-center justify-center rounded-md border bg-white bg-white px-4 py-3 text-base font-medium text-indigo-700 shadow-sm hover:bg-indigo-50 sm:px-8"
href={baseUrl}> href={HOME_URL}>
Get started Get started
</a> </a>
<a <a
className="bg-primary-600 flex items-center justify-center rounded-md border border-transparent px-4 py-3 text-base font-medium text-white shadow-sm hover:bg-opacity-70 sm:px-8" className="bg-primary-500 flex items-center justify-center rounded-md border border-transparent px-4 py-3 text-base font-medium text-white shadow-sm hover:bg-opacity-70 sm:px-8"
href="#"> href="#">
Live demo Live demo
</a> </a>
@ -118,7 +118,7 @@ export default function LandingPage() {
/> />
<div className="relative"> <div className="relative">
<LeftTextCard <LeftTextCard
description="An offer profile includes not only offers that a person get in their application cycle, but also background information such as education and work experience. Use offer profiles to help you better contaxtualize offers." description="An offer profile includes not only offers that a person received in their application cycle, but also background information such as education and work experience. Use offer profiles to help you better contextualize offers."
icon={ icon={
<InformationCircleIcon <InformationCircleIcon
aria-hidden="true" aria-hidden="true"
@ -161,13 +161,13 @@ export default function LandingPage() {
</div> </div>
{/* Gradient Feature Section */} {/* Gradient Feature Section */}
<div className="bg-gradient-to-r from-purple-800 to-indigo-700"> <div className="to-primary-600 bg-gradient-to-r from-purple-800">
<div className="mx-auto max-w-4xl px-4 py-16 sm:px-6 sm:pt-20 sm:pb-24 lg:max-w-7xl lg:px-8 lg:pt-24"> <div className="mx-auto max-w-4xl px-4 py-16 sm:px-6 sm:pt-20 sm:pb-24 lg:max-w-7xl lg:px-8 lg:pt-24">
<h2 className="flex justify-center text-4xl font-bold tracking-tight text-white"> <h2 className="flex justify-center text-4xl font-bold tracking-tight text-white">
Your privacy is our priority. Your privacy is our priority.
</h2> </h2>
<p className="mt-4 flex flex-row justify-center text-lg text-purple-200"> <p className="text-primary-100 mt-4 flex flex-row justify-center text-lg">
All offer profiles are anonymised and we do not store information All offer profiles are anonymized and we do not store information
about your personal identity. about your personal identity.
</p> </p>
<div className="mt-12 grid grid-cols-1 gap-x-6 gap-y-12 sm:grid-cols-2 lg:mt-16 lg:grid-cols-3 lg:gap-x-8 lg:gap-y-16"> <div className="mt-12 grid grid-cols-1 gap-x-6 gap-y-12 sm:grid-cols-2 lg:mt-16 lg:grid-cols-3 lg:gap-x-8 lg:gap-y-16">
@ -185,7 +185,7 @@ export default function LandingPage() {
<h3 className="text-lg font-medium text-white"> <h3 className="text-lg font-medium text-white">
{feature.name} {feature.name}
</h3> </h3>
<p className="mt-2 text-base text-purple-200"> <p className="text-primary-100 mt-2 text-base">
{feature.description} {feature.description}
</p> </p>
</div> </div>
@ -200,14 +200,14 @@ export default function LandingPage() {
<div className="mx-auto max-w-4xl py-16 px-4 sm:px-6 sm:py-24 lg:flex lg:max-w-7xl lg:items-center lg:justify-between lg:px-8"> <div className="mx-auto max-w-4xl py-16 px-4 sm:px-6 sm:py-24 lg:flex lg:max-w-7xl lg:items-center lg:justify-between lg:px-8">
<h2 className="text-4xl font-bold tracking-tight text-gray-900 sm:text-4xl"> <h2 className="text-4xl font-bold tracking-tight text-gray-900 sm:text-4xl">
<span className="block">Ready to get started?</span> <span className="block">Ready to get started?</span>
<span className="-mb-1 block bg-gradient-to-r from-purple-600 to-indigo-600 bg-clip-text pb-1 text-transparent"> <span className="to-primary-600 -mb-1 block bg-gradient-to-r from-purple-600 bg-clip-text pb-1 text-transparent">
Create your own offer profile today. Create your own offer profile today.
</span> </span>
</h2> </h2>
<div className="mt-6 space-y-4 sm:flex sm:space-y-0 sm:space-x-5"> <div className="mt-6 space-y-4 sm:flex sm:space-y-0 sm:space-x-5">
<a <a
className="flex items-center justify-center rounded-md border border-transparent bg-gradient-to-r from-purple-600 to-indigo-600 bg-origin-border px-4 py-3 text-base font-medium text-white shadow-sm hover:from-purple-700 hover:to-indigo-700" className="to-primary-500 flex items-center justify-center rounded-md border border-transparent bg-gradient-to-r from-purple-600 bg-origin-border px-4 py-3 text-base font-medium text-white shadow-sm hover:from-purple-700 hover:to-indigo-700"
href={baseUrl}> href={HOME_URL}>
Get Started Get Started
</a> </a>
</div> </div>

@ -10,6 +10,7 @@ import type {
BackgroundDisplayData, BackgroundDisplayData,
OfferDisplayData, OfferDisplayData,
} from '~/components/offers/types'; } from '~/components/offers/types';
import { HOME_URL } from '~/components/offers/types';
import type { JobTitleType } from '~/components/shared/JobTitles'; import type { JobTitleType } from '~/components/shared/JobTitles';
import { getLabelForJobTitleType } from '~/components/shared/JobTitles'; import { getLabelForJobTitleType } from '~/components/shared/JobTitles';
@ -46,7 +47,7 @@ export default function OfferProfile() {
enabled: typeof offerProfileId === 'string', enabled: typeof offerProfileId === 'string',
onSuccess: (data: Profile) => { onSuccess: (data: Profile) => {
if (!data) { if (!data) {
router.push('/offers/home'); router.push(HOME_URL);
} }
// If the profile is not editable with a wrong token, redirect to the profile page // If the profile is not editable with a wrong token, redirect to the profile page
if (!data?.isEditable && token !== '') { if (!data?.isEditable && token !== '') {
@ -148,7 +149,7 @@ export default function OfferProfile() {
}, },
onSuccess: () => { onSuccess: () => {
trpcContext.invalidateQueries(['offers.profile.listOne']); trpcContext.invalidateQueries(['offers.profile.listOne']);
router.push('/offers/home'); router.push(HOME_URL);
showToast({ showToast({
title: `Offers profile successfully deleted!`, title: `Offers profile successfully deleted!`,
variant: 'success', variant: 'success',

@ -86,10 +86,16 @@ export default function SubmitResumeForm({
setValue, setValue,
reset, reset,
watch, watch,
clearErrors,
formState: { errors, isDirty, dirtyFields }, formState: { errors, isDirty, dirtyFields },
} = useForm<IFormInput>({ } = useForm<IFormInput>({
defaultValues: { defaultValues: {
additionalInfo: '',
experience: '',
isChecked: false, isChecked: false,
location: '',
role: '',
title: '',
...initFormDetails, ...initFormDetails,
}, },
}); });
@ -296,7 +302,7 @@ export default function SubmitResumeForm({
options={ROLES} options={ROLES}
placeholder=" " placeholder=" "
required={true} required={true}
onChange={(val) => setValue('role', val)} onChange={(val) => onValueChange('role', val)}
/> />
<Select <Select
{...register('experience', { required: true })} {...register('experience', { required: true })}
@ -305,7 +311,7 @@ export default function SubmitResumeForm({
options={EXPERIENCES} options={EXPERIENCES}
placeholder=" " placeholder=" "
required={true} required={true}
onChange={(val) => setValue('experience', val)} onChange={(val) => onValueChange('experience', val)}
/> />
</div> </div>
<Select <Select
@ -315,7 +321,7 @@ export default function SubmitResumeForm({
options={LOCATIONS} options={LOCATIONS}
placeholder=" " placeholder=" "
required={true} required={true}
onChange={(val) => setValue('location', val)} onChange={(val) => onValueChange('location', val)}
/> />
{/* Upload resume form */} {/* Upload resume form */}
{isNewForm && ( {isNewForm && (
@ -335,6 +341,16 @@ export default function SubmitResumeForm({
: 'border-slate-300', : 'border-slate-300',
'flex cursor-pointer justify-center rounded-md border-2 border-dashed bg-slate-100 py-4', 'flex cursor-pointer justify-center rounded-md border-2 border-dashed bg-slate-100 py-4',
)}> )}>
<input
{...register('file', { required: true })}
{...getInputProps()}
accept="application/pdf"
className="sr-only"
disabled={isLoading}
id="file-upload"
name="file-upload"
type="file"
/>
<div className="space-y-1 text-center"> <div className="space-y-1 text-center">
{resumeFile == null ? ( {resumeFile == null ? (
<ArrowUpCircleIcon className="text-primary-500 m-auto h-10 w-10" /> <ArrowUpCircleIcon className="text-primary-500 m-auto h-10 w-10" />
@ -345,29 +361,15 @@ export default function SubmitResumeForm({
{resumeFile.name} {resumeFile.name}
</p> </p>
)} )}
<div className="flex items-center text-sm"> <label
<label className="focus-within:ring-primary-500 flex items-center rounded-md text-sm focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2"
className="focus-within:ring-primary-500 rounded-md focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2" htmlFor="file-upload">
htmlFor="file-upload"> <span className="font-medium">Drop file here</span>
<span className="font-medium">Drop file here</span> <span className="mr-1 ml-1 font-light">or</span>
<span className="mr-1 ml-1 font-light">or</span> <span className="text-primary-600 hover:text-primary-400 cursor-pointer font-medium">
<span className="text-primary-600 hover:text-primary-400 cursor-pointer font-medium"> {resumeFile == null ? 'Select file' : 'Replace file'}
{resumeFile == null </span>
? 'Select file' </label>
: 'Replace file'}
</span>
<input
{...register('file', { required: true })}
{...getInputProps()}
accept="application/pdf"
className="sr-only"
disabled={isLoading}
id="file-upload"
name="file-upload"
type="file"
/>
</label>
</div>
<p className="text-xs text-slate-500"> <p className="text-xs text-slate-500">
PDF up to {FILE_SIZE_LIMIT_MB}MB PDF up to {FILE_SIZE_LIMIT_MB}MB
</p> </p>
@ -394,8 +396,18 @@ export default function SubmitResumeForm({
<CheckboxInput <CheckboxInput
{...register('isChecked', { required: true })} {...register('isChecked', { required: true })}
disabled={isLoading} disabled={isLoading}
errorMessage={
!errors.file && errors.isChecked
? 'Please tick the checkbox after reading through the guidelines.'
: undefined
}
label="I have read and will follow the guidelines stated." label="I have read and will follow the guidelines stated."
onChange={(val) => setValue('isChecked', val)} onChange={(val) => {
if (val) {
clearErrors('isChecked');
}
setValue('isChecked', val);
}}
/> />
</> </>
)} )}

@ -106,7 +106,6 @@ export const questionsQuestionEncounterRouter = createProtectedRouter()
}, },
}) })
.mutation('update', { .mutation('update', {
//
input: z.object({ input: z.object({
companyId: z.string().optional(), companyId: z.string().optional(),
id: z.string(), id: z.string(),

@ -14,7 +14,7 @@ export const questionsQuestionRouter = createProtectedRouter()
cursor: z cursor: z
.object({ .object({
idCursor: z.string().optional(), idCursor: z.string().optional(),
lastSeenCursor: z.date().optional(), lastSeenCursor: z.date().nullish().optional(),
upvoteCursor: z.number().optional(), upvoteCursor: z.number().optional(),
}) })
.nullish(), .nullish(),
@ -49,8 +49,6 @@ export const questionsQuestionRouter = createProtectedRouter()
}, },
]; ];
const toSkip = cursor ? 1 : 0;
const questionsData = await ctx.prisma.questionsQuestion.findMany({ const questionsData = await ctx.prisma.questionsQuestion.findMany({
cursor: cursor:
cursor !== undefined cursor !== undefined
@ -81,7 +79,6 @@ export const questionsQuestionRouter = createProtectedRouter()
votes: true, votes: true,
}, },
orderBy: sortCondition, orderBy: sortCondition,
skip: toSkip,
take: input.limit + 1, take: input.limit + 1,
where: { where: {
...(input.questionTypes.length > 0 ...(input.questionTypes.length > 0

@ -7,6 +7,7 @@ type Props = Readonly<{
defaultValue?: boolean; defaultValue?: boolean;
description?: string; description?: string;
disabled?: boolean; disabled?: boolean;
errorMessage?: string;
label: string; label: string;
name?: string; name?: string;
onChange?: ( onChange?: (
@ -21,6 +22,7 @@ function CheckboxInput(
defaultValue, defaultValue,
description, description,
disabled = false, disabled = false,
errorMessage,
label, label,
name, name,
value, value,
@ -30,59 +32,67 @@ function CheckboxInput(
) { ) {
const id = useId(); const id = useId();
const descriptionId = useId(); const descriptionId = useId();
const errorId = useId();
return ( return (
<div <div>
className={clsx( <div
'relative flex', className={clsx(
// Vertically center only when there's no description. 'relative flex',
description == null && 'items-center', // Vertically center only when there's no description.
)}> description == null && 'items-center',
<div className="flex h-5 items-center"> )}>
<input <div className="flex h-5 items-center">
ref={ref} <input
aria-describedby={description != null ? descriptionId : undefined} ref={ref}
checked={value} aria-describedby={description != null ? descriptionId : undefined}
className={clsx( checked={value}
'h-4 w-4 rounded border-slate-300',
disabled
? 'bg-slate-100 text-slate-400'
: 'text-primary-600 focus:ring-primary-500',
)}
defaultChecked={defaultValue}
disabled={disabled}
id={id}
name={name}
type="checkbox"
onChange={
onChange != null
? (event) => {
onChange?.(event.target.checked, event);
}
: undefined
}
/>
</div>
<div className="ml-3 text-sm">
<label
className={clsx(
'block font-medium',
disabled ? 'text-slate-400' : 'text-slate-700',
)}
htmlFor={id}>
{label}
</label>
{description && (
<p
className={clsx( className={clsx(
'text-xs', 'h-4 w-4 rounded border-slate-300',
disabled ? 'text-slate-400' : 'text-slate-500', disabled
? 'bg-slate-100 text-slate-400'
: 'text-primary-600 focus:ring-primary-500',
)} )}
id={descriptionId}> defaultChecked={defaultValue}
{description} disabled={disabled}
</p> id={id}
)} name={name}
type="checkbox"
onChange={(event) => {
if (!onChange) {
return;
}
onChange(event.target.checked, event);
}}
/>
</div>
<div className="ml-3 text-sm">
<label
className={clsx(
'block font-medium',
disabled ? 'text-slate-400' : 'text-slate-700',
)}
htmlFor={id}>
{label}
</label>
{description && (
<p
className={clsx(
'text-xs',
disabled ? 'text-slate-400' : 'text-slate-500',
)}
id={descriptionId}>
{description}
</p>
)}
</div>
</div> </div>
{errorMessage && (
<p className="text-danger-600 mt-2 text-sm" id={errorId}>
{errorMessage}
</p>
)}
</div> </div>
); );
} }

Loading…
Cancel
Save