diff --git a/apps/portal/prisma/migrations/20221104042559_add_reference_to_analysed_offer_in_analysis_unit/migration.sql b/apps/portal/prisma/migrations/20221104042559_add_reference_to_analysed_offer_in_analysis_unit/migration.sql new file mode 100644 index 00000000..3a29e11f --- /dev/null +++ b/apps/portal/prisma/migrations/20221104042559_add_reference_to_analysed_offer_in_analysis_unit/migration.sql @@ -0,0 +1,16 @@ +/* + Warnings: + + - You are about to drop the column `companyId` on the `OffersAnalysisUnit` table. All the data in the column will be lost. + - Added the required column `analysedOfferId` to the `OffersAnalysisUnit` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "OffersAnalysisUnit" DROP CONSTRAINT "OffersAnalysisUnit_companyId_fkey"; + +-- AlterTable +ALTER TABLE "OffersAnalysisUnit" DROP COLUMN "companyId", +ADD COLUMN "analysedOfferId" TEXT NOT NULL; + +-- AddForeignKey +ALTER TABLE "OffersAnalysisUnit" ADD CONSTRAINT "OffersAnalysisUnit_analysedOfferId_fkey" FOREIGN KEY ("analysedOfferId") REFERENCES "OffersOffer"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/apps/portal/prisma/schema.prisma b/apps/portal/prisma/schema.prisma index e39941f2..cbf65808 100644 --- a/apps/portal/prisma/schema.prisma +++ b/apps/portal/prisma/schema.prisma @@ -104,7 +104,6 @@ model Company { questionsQuestionEncounter QuestionsQuestionEncounter[] OffersExperience OffersExperience[] OffersOffer OffersOffer[] - OffersAnalysisUnit OffersAnalysisUnit[] } model Country { @@ -368,6 +367,7 @@ model OffersOffer { offersAnalysis OffersAnalysis? @relation("HighestOverallOffer") offersAnalysisUnit OffersAnalysisUnit[] + OffersAnalysisUnit OffersAnalysisUnit[] @relation("Analysed Offer") } model OffersIntern { @@ -419,8 +419,8 @@ model OffersAnalysis { model OffersAnalysisUnit { id String @id @default(cuid()) - company Company @relation(fields: [companyId], references: [id]) - companyId String + analysedOffer OffersOffer @relation("Analysed Offer", fields: [analysedOfferId], references: [id]) + analysedOfferId String percentile Float noOfSimilarOffers Int diff --git a/apps/portal/src/components/offers/Breadcrumb.tsx b/apps/portal/src/components/offers/Breadcrumbs.tsx similarity index 100% rename from apps/portal/src/components/offers/Breadcrumb.tsx rename to apps/portal/src/components/offers/Breadcrumbs.tsx diff --git a/apps/portal/src/components/offers/EducationFields.ts b/apps/portal/src/components/offers/EducationFields.ts new file mode 100644 index 00000000..6818b9ab --- /dev/null +++ b/apps/portal/src/components/offers/EducationFields.ts @@ -0,0 +1,16 @@ +import { emptyOption } from './constants'; + +export const EducationFieldLabels = [ + 'Business Analytics', + 'Computer Science', + 'Data Science and Analytics', + 'Information Security', + 'Information Systems', +]; + +export const EducationFieldOptions = [emptyOption].concat( + EducationFieldLabels.map((label) => ({ + label, + value: label.replace(/\s+/g, '-').toLowerCase(), + })), +); diff --git a/apps/portal/src/components/offers/EducationLevels.ts b/apps/portal/src/components/offers/EducationLevels.ts new file mode 100644 index 00000000..176b2519 --- /dev/null +++ b/apps/portal/src/components/offers/EducationLevels.ts @@ -0,0 +1,18 @@ +import { emptyOption } from './constants'; + +export const EducationLevelLabels = [ + 'Bachelor', + 'Diploma', + 'Masters', + 'PhD', + 'Professional', + 'Secondary', + 'Self-taught', +]; + +export const EducationLevelOptions = [emptyOption].concat( + EducationLevelLabels.map((label) => ({ + label, + value: label.replace(/\s+/g, '-').toLowerCase(), + })), +); diff --git a/apps/portal/src/components/offers/InternshipCycles.ts b/apps/portal/src/components/offers/InternshipCycles.ts new file mode 100644 index 00000000..1f90539f --- /dev/null +++ b/apps/portal/src/components/offers/InternshipCycles.ts @@ -0,0 +1,18 @@ +import { emptyOption } from './constants'; + +export const InternshipCycleLabels = [ + 'Spring', + 'Summer', + 'Fall', + 'Winter', + 'Half year', + 'Full year', + 'Others', +]; + +export const InternshipCycleOptions = [emptyOption].concat( + InternshipCycleLabels.map((label) => ({ + label, + value: label.replace(/\s+/g, '-').toLowerCase(), + })), +); diff --git a/apps/portal/src/components/offers/JobTypeTabs.tsx b/apps/portal/src/components/offers/JobTypeTabs.tsx index 8ea87bc6..22d70ea7 100644 --- a/apps/portal/src/components/offers/JobTypeTabs.tsx +++ b/apps/portal/src/components/offers/JobTypeTabs.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import { JobType } from '@prisma/client'; -import { JobTypeLabel } from './types'; +import { JobTypeLabel } from '~/components/offers/constants'; type Props = Readonly<{ onChange: (jobType: JobType) => void; diff --git a/apps/portal/src/components/offers/Years.ts b/apps/portal/src/components/offers/Years.ts new file mode 100644 index 00000000..da9ab8e3 --- /dev/null +++ b/apps/portal/src/components/offers/Years.ts @@ -0,0 +1,8 @@ +const NUM_YEARS = 5; +export const FutureYearsOptions = Array.from({ length: NUM_YEARS }, (_, i) => { + const year = new Date().getFullYear() + i; + return { + label: String(year), + value: year, + }; +}); diff --git a/apps/portal/src/components/offers/constants.ts b/apps/portal/src/components/offers/constants.ts index d49dca1a..e84dfd4e 100644 --- a/apps/portal/src/components/offers/constants.ts +++ b/apps/portal/src/components/offers/constants.ts @@ -1,78 +1,14 @@ -import { EducationBackgroundType } from './types'; +export const HOME_URL = '/offers'; -export const emptyOption = '----'; +export const JobTypeLabel = { + FULLTIME: 'Full-time', + INTERN: 'Internship', +}; -export const internshipCycleOptions = [ - { - label: 'Summer', - value: 'Summer', - }, - { - label: 'Winter', - value: 'Winter', - }, - { - label: 'Spring', - value: 'Spring', - }, - { - label: 'Fall', - value: 'Fall', - }, - { - label: 'Full year', - value: 'Full year', - }, -]; - -export const yearOptions = [ - { - label: '2021', - value: 2021, - }, - { - label: '2022', - value: 2022, - }, - { - label: '2023', - value: 2023, - }, - { - label: '2024', - value: 2024, - }, -]; - -export const educationLevelOptions = Object.entries( - EducationBackgroundType, -).map(([, value]) => ({ - label: value, - value, -})); - -export const educationFieldOptions = [ - { - label: 'Computer Science', - value: 'Computer Science', - }, - { - label: 'Information Security', - value: 'Information Security', - }, - { - label: 'Information Systems', - value: 'Information Systems', - }, - { - label: 'Business Analytics', - value: 'Business Analytics', - }, - { - label: 'Data Science and Analytics', - value: 'Data Science and Analytics', - }, -]; +export const emptyOption = { + label: '', + value: '', +}; export enum FieldError { NON_NEGATIVE_NUMBER = 'Please fill in a non-negative number in this field.', diff --git a/apps/portal/src/components/offers/dashboard/DashboardOfferCard.tsx b/apps/portal/src/components/offers/dashboard/DashboardOfferCard.tsx index 722263b6..3b013c2c 100644 --- a/apps/portal/src/components/offers/dashboard/DashboardOfferCard.tsx +++ b/apps/portal/src/components/offers/dashboard/DashboardOfferCard.tsx @@ -5,6 +5,7 @@ import { } from '@heroicons/react/20/solid'; import { JobType } from '@prisma/client'; +import { JobTypeLabel } from '~/components/offers/constants'; import type { JobTitleType } from '~/components/shared/JobTitles'; import { getLabelForJobTitleType } from '~/components/shared/JobTitles'; @@ -33,32 +34,33 @@ export default function DashboardProfileCard({

- {getLabelForJobTitleType(title as JobTitleType)} + {getLabelForJobTitleType(title as JobTitleType)}{' '} + {jobType && <>({JobTypeLabel[jobType]})}

{company?.name && ( -
+
)} {location && ( -
+
)} {level && ( -
+
diff --git a/apps/portal/src/components/offers/features/LeftTextCard.tsx b/apps/portal/src/components/offers/features/LeftTextCard.tsx index b4fac765..867b24b7 100644 --- a/apps/portal/src/components/offers/features/LeftTextCard.tsx +++ b/apps/portal/src/components/offers/features/LeftTextCard.tsx @@ -2,7 +2,7 @@ import type { StaticImageData } from 'next/image'; import Image from 'next/image'; import type { ReactNode } from 'react'; -import { HOME_URL } from '~/components/offers/types'; +import { HOME_URL } from '../constants'; type LeftTextCardProps = Readonly<{ description: string; diff --git a/apps/portal/src/components/offers/features/RightTextCard.tsx b/apps/portal/src/components/offers/features/RightTextCard.tsx index 9ca0f949..028dc57b 100644 --- a/apps/portal/src/components/offers/features/RightTextCard.tsx +++ b/apps/portal/src/components/offers/features/RightTextCard.tsx @@ -2,7 +2,7 @@ import type { StaticImageData } from 'next/image'; import Image from 'next/image'; import type { ReactNode } from 'react'; -import { HOME_URL } from '~/components/offers/types'; +import { HOME_URL } from '../constants'; type RightTextCarddProps = Readonly<{ description: string; diff --git a/apps/portal/src/components/offers/offerAnalysis/OfferAnalysis.tsx b/apps/portal/src/components/offers/offerAnalysis/OfferAnalysis.tsx index e7e6199b..d229eb52 100644 --- a/apps/portal/src/components/offers/offerAnalysis/OfferAnalysis.tsx +++ b/apps/portal/src/components/offers/offerAnalysis/OfferAnalysis.tsx @@ -109,13 +109,13 @@ export default function OfferAnalysis({ return (
- {isError && ( + {isError ? (

An error occurred while generating profile analysis.

- )} - {isLoading && } - {!isError && !isLoading && ( + ) : isLoading ? ( + + ) : (
- + ); } diff --git a/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx b/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx index b72641d8..513d0de7 100644 --- a/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx +++ b/apps/portal/src/components/offers/offersSubmission/OffersProfileSave.tsx @@ -1,5 +1,5 @@ import { signIn, useSession } from 'next-auth/react'; -import { useState } from 'react'; +import type { UseQueryResult } from 'react-query'; import { DocumentDuplicateIcon } from '@heroicons/react/20/solid'; import { BookmarkIcon as BookmarkOutlineIcon } from '@heroicons/react/24/outline'; import { BookmarkIcon as BookmarkSolidIcon } from '@heroicons/react/24/solid'; @@ -11,6 +11,7 @@ import { copyProfileLink, getProfileLink } from '~/utils/offers/link'; import { trpc } from '~/utils/trpc'; type OfferProfileSaveProps = Readonly<{ + isSavedQuery: UseQueryResult; profileId: string; token?: string; }>; @@ -18,10 +19,10 @@ type OfferProfileSaveProps = Readonly<{ export default function OffersProfileSave({ profileId, token, + isSavedQuery: { data: isSaved, isLoading }, }: OfferProfileSaveProps) { const { showToast } = useToast(); const { event: gaEvent } = useGoogleAnalytics(); - const [isSaved, setSaved] = useState(false); const { data: session, status } = useSession(); const saveMutation = trpc.useMutation( @@ -47,15 +48,6 @@ export default function OffersProfileSave({ }, ); - const isSavedQuery = trpc.useQuery( - [`offers.profile.isSaved`, { profileId, userId: session?.user?.id }], - { - onSuccess: (res) => { - setSaved(res); - }, - }, - ); - const trpcContext = trpc.useContext(); const handleSave = () => { if (status === 'unauthenticated') { @@ -93,7 +85,6 @@ export default function OffersProfileSave({
diff --git a/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx index 06415aad..a03782dd 100644 --- a/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx +++ b/apps/portal/src/components/offers/offersSubmission/OffersSubmissionForm.tsx @@ -4,11 +4,11 @@ import type { SubmitHandler } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form'; import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/20/solid'; import { JobType } from '@prisma/client'; -import { Button } from '@tih/ui'; +import { Button, Spinner, useToast } from '@tih/ui'; import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics'; -import type { BreadcrumbStep } from '~/components/offers/Breadcrumb'; -import { Breadcrumbs } from '~/components/offers/Breadcrumb'; +import type { BreadcrumbStep } from '~/components/offers/Breadcrumbs'; +import { Breadcrumbs } from '~/components/offers/Breadcrumbs'; import BackgroundForm from '~/components/offers/offersSubmission/submissionForm/BackgroundForm'; import OfferDetailsForm from '~/components/offers/offersSubmission/submissionForm/OfferDetailsForm'; import type { @@ -102,8 +102,9 @@ export default function OffersSubmissionForm({ token: editToken, }); const [isSubmitted, setIsSubmitted] = useState(false); - const { event: gaEvent } = useGoogleAnalytics(); + const { event: gaEvent } = useGoogleAnalytics(); + const { showToast } = useToast(); const router = useRouter(); const pageRef = useRef(null); const scrollToTop = () => @@ -115,7 +116,7 @@ export default function OffersSubmissionForm({ const { handleSubmit, trigger, - formState: { isSubmitting, isSubmitSuccessful }, + formState: { isSubmitting }, } = formMethods; const generateAnalysisMutation = trpc.useMutation( @@ -123,6 +124,10 @@ export default function OffersSubmissionForm({ { onError(error) { console.error(error.message); + showToast({ + title: 'Error generating analysis.', + variant: 'failure', + }); }, onSuccess() { router.push( @@ -132,13 +137,7 @@ export default function OffersSubmissionForm({ }, ); - const steps = [ - , - , - ]; + const steps = [, ]; const breadcrumbSteps: Array = [ { @@ -157,14 +156,14 @@ export default function OffersSubmissionForm({ }, ]; - const goToNextStep = async (currStep: number) => { - if (currStep === 0) { + const setStepWithValidation = async (nextStep: number) => { + if (nextStep === 1) { const result = await trigger('offers'); if (!result) { return; } } - setStep(step + 1); + setStep(nextStep); }; const mutationpath = @@ -175,16 +174,30 @@ export default function OffersSubmissionForm({ const createOrUpdateMutation = trpc.useMutation([mutationpath], { onError(error) { console.error(error.message); + showToast({ + title: + editProfileId && editToken + ? 'Error updating offer profile.' + : 'Error creating offer profile.', + variant: 'failure', + }); }, onSuccess(data) { setParams({ profileId: data.id, token: data.token }); setIsSubmitted(true); + showToast({ + title: + editProfileId && editToken + ? 'Offer profile updated successfully!' + : 'Offer profile created successfully!', + variant: 'success', + }); }, }); const onSubmit: SubmitHandler = async (data) => { const result = await trigger(); - if (!result || isSubmitting || isSubmitSuccessful) { + if (!result || isSubmitting || createOrUpdateMutation.isLoading) { return; } @@ -263,14 +276,16 @@ export default function OffersSubmissionForm({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - return ( + return generateAnalysisMutation.isLoading ? ( + + ) : (
@@ -288,7 +303,7 @@ export default function OffersSubmissionForm({ label="Next" variant="primary" onClick={() => { - goToNextStep(step); + setStepWithValidation(step + 1); gaEvent({ action: 'offers.profile_submission_navigate_next', category: 'submission', @@ -315,9 +330,16 @@ export default function OffersSubmissionForm({ }} />
diff --git a/apps/portal/src/components/offers/offersSubmission/submissionForm/OfferDetailsForm.tsx b/apps/portal/src/components/offers/offersSubmission/submissionForm/OfferDetailsForm.tsx index 7c9e52e6..1fc38fe2 100644 --- a/apps/portal/src/components/offers/offersSubmission/submissionForm/OfferDetailsForm.tsx +++ b/apps/portal/src/components/offers/offersSubmission/submissionForm/OfferDetailsForm.tsx @@ -22,20 +22,16 @@ import { defaultFullTimeOfferValues, defaultInternshipOfferValues, } from '../OffersSubmissionForm'; -import { - emptyOption, - FieldError, - internshipCycleOptions, - yearOptions, -} from '../../constants'; +import { FieldError, JobTypeLabel } from '../../constants'; import FormMonthYearPicker from '../../forms/FormMonthYearPicker'; import FormSection from '../../forms/FormSection'; import FormSelect from '../../forms/FormSelect'; import FormTextArea from '../../forms/FormTextArea'; import FormTextInput from '../../forms/FormTextInput'; +import { InternshipCycleOptions } from '../../InternshipCycles'; import JobTypeTabs from '../../JobTypeTabs'; import type { OfferFormData } from '../../types'; -import { JobTypeLabel } from '../../types'; +import { FutureYearsOptions } from '../../Years'; import { Currency, CURRENCY_OPTIONS, @@ -384,8 +380,7 @@ function InternshipOfferDetailsForm({ display="block" errorMessage={offerFields?.offersIntern?.internshipCycle?.message} label="Internship Cycle" - options={internshipCycleOptions} - placeholder={emptyOption} + options={InternshipCycleOptions} required={true} {...register(`offers.${index}.offersIntern.internshipCycle`, { required: FieldError.REQUIRED, @@ -395,8 +390,7 @@ function InternshipOfferDetailsForm({ display="block" errorMessage={offerFields?.offersIntern?.startYear?.message} label="Internship Year" - options={yearOptions} - placeholder={emptyOption} + options={FutureYearsOptions} required={true} {...register(`offers.${index}.offersIntern.startYear`, { required: FieldError.REQUIRED, @@ -522,14 +516,11 @@ function OfferDetailsFormArray({ ); } -type OfferDetailsFormProps = Readonly<{ - defaultJobType?: JobType; -}>; - -export default function OfferDetailsForm({ - defaultJobType = JobType.FULLTIME, -}: OfferDetailsFormProps) { - const [jobType, setJobType] = useState(defaultJobType); +export default function OfferDetailsForm() { + const watchJobType = useWatch({ + name: `offers.0.jobType`, + }); + const [jobType, setJobType] = useState(watchJobType as JobType); const [isDialogOpen, setDialogOpen] = useState(false); const { control } = useFormContext(); const fieldArrayValues = useFieldArray({ control, name: 'offers' }); @@ -576,8 +567,8 @@ export default function OfferDetailsForm({ label="Switch" variant="primary" onClick={() => { - toggleJobType(); setDialogOpen(false); + toggleJobType(); }} /> } diff --git a/apps/portal/src/components/offers/profile/EducationCard.tsx b/apps/portal/src/components/offers/profile/EducationCard.tsx index c885ef5a..9549e423 100644 --- a/apps/portal/src/components/offers/profile/EducationCard.tsx +++ b/apps/portal/src/components/offers/profile/EducationCard.tsx @@ -13,12 +13,12 @@ export default function EducationCard({ education: { type, field, startDate, endDate, school }, }: Props) { return ( -
-
-
-
+
+
+
+
- + {field ? `${type ?? 'N/A'}, ${field}` : type ?? `N/A`}
diff --git a/apps/portal/src/components/offers/profile/OfferCard.tsx b/apps/portal/src/components/offers/profile/OfferCard.tsx index 3d03e1ef..42212fce 100644 --- a/apps/portal/src/components/offers/profile/OfferCard.tsx +++ b/apps/portal/src/components/offers/profile/OfferCard.tsx @@ -1,13 +1,15 @@ import { - BuildingOffice2Icon, - ChatBubbleBottomCenterTextIcon, - CurrencyDollarIcon, - ScaleIcon, -} from '@heroicons/react/24/outline'; -import { HorizontalDivider } from '@tih/ui'; + ArrowTrendingUpIcon, + BuildingOfficeIcon, + MapPinIcon, +} from '@heroicons/react/20/solid'; +import { JobType } from '@prisma/client'; +import { JobTypeLabel } from '~/components/offers/constants'; import type { OfferDisplayData } from '~/components/offers/types'; -import { JobTypeLabel } from '~/components/offers/types'; + +import { getLocationDisplayText } from '~/utils/offers/string'; +import { getDurationDisplayText } from '~/utils/offers/time'; type Props = Readonly<{ offer: OfferDisplayData; @@ -33,33 +35,55 @@ export default function OfferCard({ }: Props) { function UpperSection() { return ( -
-
-
- - - - - {location ? `${companyName}, ${location.cityName}` : companyName} - +
+
+
+

+ {jobTitle} {jobType && <>({JobTypeLabel[jobType]})} +

+
+ {companyName && ( +
+
+ )} + {location && ( +
+
+ )} + {jobLevel && ( +
+
+ )} +
-
-

- {jobLevel ? `${jobTitle}, ${jobLevel}` : jobTitle}{' '} - {jobType && `(${JobTypeLabel[jobType]})`} -

+
+ {!duration && receivedMonth && ( +
+

{receivedMonth}

+
+ )} + {!!duration && ( +
+

{getDurationDisplayText(duration)}

+
+ )}
- {!duration && receivedMonth && ( -
-

{receivedMonth}

-
- )} - {duration && ( -
-

{`${duration} months`}

-
- )}
); } @@ -75,60 +99,72 @@ export default function OfferCard({ } return ( - <> - -
-
- {(totalCompensation || monthlySalary) && ( -
- - - - -

- {totalCompensation && `TC: ${totalCompensation}`} - {monthlySalary && `Monthly Salary: ${monthlySalary}`} -

-
-
- )} - {(base || stocks || bonus) && totalCompensation && ( -
-

- Base / year: {base ?? 'N/A'} ⋅ Stocks / year:{' '} - {stocks ?? 'N/A'} ⋅ Bonus / year: {bonus ?? 'N/A'} -

-
- )} -
+
+
+ {jobType === JobType.FULLTIME + ? totalCompensation && ( +
+
+ Total Compensation +
+
+ {totalCompensation} +
+
+ ) + : monthlySalary && ( +
+
+ Monthly Salary +
+
+ {monthlySalary} +
+
+ )} + {base && ( +
+
+ Base Salary +
+
{base}
+
+ )} + {stocks && ( +
+
Stocks
+
{stocks}
+
+ )} + {bonus && ( +
+
Bonus
+
{bonus}
+
+ )} {negotiationStrategy && ( -
-
- - - - - "{negotiationStrategy}" - -
+
+
+ Negotiation Strategy +
+
+ {negotiationStrategy} +
)} {otherComment && ( -
-
- - - - "{otherComment}" -
+
+
Others
+
{otherComment}
)} -
- +
+
); } + return ( -
+
diff --git a/apps/portal/src/components/offers/profile/ProfileComments.tsx b/apps/portal/src/components/offers/profile/ProfileComments.tsx index 5654ed5e..0eeaa1a3 100644 --- a/apps/portal/src/components/offers/profile/ProfileComments.tsx +++ b/apps/portal/src/components/offers/profile/ProfileComments.tsx @@ -1,13 +1,7 @@ import { signIn, useSession } from 'next-auth/react'; import { useState } from 'react'; import { ClipboardDocumentIcon, ShareIcon } from '@heroicons/react/24/outline'; -import { - Button, - HorizontalDivider, - Spinner, - TextArea, - useToast, -} from '@tih/ui'; +import { Button, Spinner, TextArea, useToast } from '@tih/ui'; import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics'; import ExpandableCommentCard from '~/components/offers/profile/comments/ExpandableCommentCard'; @@ -110,10 +104,10 @@ export default function ProfileComments({ ); } return ( -
-
+
+
-
+
{isEditable && ( @@ -169,57 +163,60 @@ export default function ProfileComments({
-

Discussions

- {isEditable || session?.user?.name ? ( -
-