Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Textarea from '../../fields/Textarea';
import { Button, ButtonSize, ButtonVariant } from '../../buttons/Button';
import { labels } from '../../../lib';
import {
opportunityCreateOrganizationSchema,
opportunityEditOrganizationSchema,
SocialMediaType,
} from '../../../lib/schema/opportunity';
Expand Down Expand Up @@ -345,6 +346,12 @@ export const OpportunityEditOrganizationModal = ({
...clearOrganizationImageMutationOptions(),
});

// if there was no organization we use create schema to require name
const editSchema =
opportunity && !opportunity.organization
? opportunityCreateOrganizationSchema
: opportunityEditOrganizationSchema;

const {
register,
control,
Expand All @@ -354,26 +361,27 @@ export const OpportunityEditOrganizationModal = ({
setValue,
watch,
} = useForm({
resolver: zodResolver(opportunityEditOrganizationSchema),
resolver: zodResolver(editSchema),
defaultValues: async () => {
const opportunityData = await promise;

// Merge all link types into a single array
const customLinks = opportunityData.organization.customLinks || [];
const socialLinks = opportunityData.organization.socialLinks || [];
const pressLinks = opportunityData.organization.pressLinks || [];
const customLinks = opportunityData.organization?.customLinks || [];
const socialLinks = opportunityData.organization?.socialLinks || [];
const pressLinks = opportunityData.organization?.pressLinks || [];
const allLinks = [...customLinks, ...socialLinks, ...pressLinks];

return {
organization: {
website: opportunityData.organization.website || '',
description: opportunityData.organization.description || '',
perks: opportunityData.organization.perks || [],
founded: opportunityData.organization.founded || undefined,
location: opportunityData.organization.location || '',
category: opportunityData.organization.category || '',
size: opportunityData.organization.size || undefined,
stage: opportunityData.organization.stage || undefined,
name: opportunityData.organization?.name || '',
website: opportunityData.organization?.website || '',
description: opportunityData.organization?.description || '',
perks: opportunityData.organization?.perks || [],
founded: opportunityData.organization?.founded || undefined,
location: opportunityData.organization?.location || '',
category: opportunityData.organization?.category || '',
size: opportunityData.organization?.size || undefined,
stage: opportunityData.organization?.stage || undefined,
links: allLinks,
},
};
Expand All @@ -389,7 +397,7 @@ export const OpportunityEditOrganizationModal = ({

await mutateAsync({
id,
payload: data as z.infer<typeof opportunityEditOrganizationSchema>,
payload: data as z.infer<typeof editSchema>,
organizationImage: organizationImageFile || undefined,
});
} catch (originalError) {
Expand Down Expand Up @@ -521,6 +529,17 @@ export const OpportunityEditOrganizationModal = ({
fileSizeLimitMB={5}
/>
</div>
{editSchema === opportunityCreateOrganizationSchema && (
<TextField
{...register('organization.name')}
type="text"
inputId="organizationName"
label="Company name"
fieldType="secondary"
valid={!errors.organization?.name}
hint={errors.organization?.name?.message}
/>
)}
<TextField
{...register('organization.website')}
type="url"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,15 @@ export const OpportunityMatchList = ({
passHref
>
<a className="flex items-center gap-3 p-2">
<SourceAvatar
source={{
image: opportunity.organization.image,
handle: opportunity.organization.name,
}}
size={ProfileImageSize.Large}
/>
{!!opportunity.organization && (
<SourceAvatar
source={{
image: opportunity.organization.image,
handle: opportunity.organization.name,
}}
size={ProfileImageSize.Large}
/>
)}
<FlexCol className="min-w-0 flex-1 gap-1">
<Typography
type={TypographyType.Body}
Expand All @@ -104,7 +106,7 @@ export const OpportunityMatchList = ({
type={TypographyType.Footnote}
color={TypographyColor.Tertiary}
>
{opportunity.organization.name} •{' '}
{opportunity.organization?.name || 'N/A'} •{' '}
<DateFormat date={match.createdAt} />
</Typography>
<div
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/features/opportunity/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export type Opportunity = {
state: OpportunityState;
title: string;
tldr: string;
organization: Organization;
organization?: Organization;
content: {
overview: OpportunityContentBlock;
};
Expand Down
10 changes: 10 additions & 0 deletions packages/shared/src/lib/schema/opportunity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ export const opportunityEditInfoSchema = z.object({
),
),
}),
organization: z.object({
name: z.string().nonempty().max(60),
}),
});

export const createOpportunityEditContentSchema = ({
Expand Down Expand Up @@ -207,3 +210,10 @@ export const opportunityEditRecruiterSchema = z.object({
bio: z.string().max(2000).optional(),
}),
});

export const opportunityCreateOrganizationSchema =
opportunityEditOrganizationSchema.extend({
organization: opportunityEditOrganizationSchema.shape.organization.extend({
name: z.string().nonempty().max(60),
}),
});
104 changes: 54 additions & 50 deletions packages/webapp/pages/jobs/[id]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -406,30 +406,32 @@ const JobPage = (): ReactElement => {
});
}}
/>
<div className="flex items-center">
<SourceAvatar
source={{
image: opportunity.organization.image,
handle: opportunity.organization.name,
}}
size={ProfileImageSize.Medium}
/>
{!!opportunity.organization && (
<div className="flex items-center">
<SourceAvatar
source={{
image: opportunity.organization.image,
handle: opportunity.organization.name,
}}
size={ProfileImageSize.Medium}
/>

<Typography
bold
type={TypographyType.Callout}
color={TypographyColor.Primary}
>
{opportunity.organization.name}{' '}
<Typography
tag={TypographyTag.Span}
color={TypographyColor.Tertiary}
className="font-normal"
bold
type={TypographyType.Callout}
color={TypographyColor.Primary}
>
Verified job
{opportunity.organization.name}{' '}
<Typography
tag={TypographyTag.Span}
color={TypographyColor.Tertiary}
className="font-normal"
>
Verified job
</Typography>
</Typography>
</Typography>
</div>
</div>
)}
{/* Recruiter */}
{!!opportunity.recruiters?.[0] && (
<div className="flex items-center gap-2">
Expand Down Expand Up @@ -704,7 +706,7 @@ const JobPage = (): ReactElement => {
}}
/>

{opportunity.organization.website && (
{!!opportunity.organization?.website && (
<Link href={opportunity.organization.website} passHref>
<Button
tag="a"
Expand All @@ -721,34 +723,36 @@ const JobPage = (): ReactElement => {
)}
</div>
{/* Company information */}
<div className="flex px-4">
<SourceAvatar
source={{
image: opportunity.organization.image,
handle: opportunity.organization.name,
}}
size={ProfileImageSize.Large}
/>
{!!opportunity.organization && (
<div className="flex px-4">
<SourceAvatar
source={{
image: opportunity.organization.image,
handle: opportunity.organization.name,
}}
size={ProfileImageSize.Large}
/>

<div className="flex flex-shrink flex-col flex-wrap">
<Typography
type={TypographyType.Body}
color={TypographyColor.Primary}
>
{opportunity.organization.name}
</Typography>
<Typography
type={TypographyType.Footnote}
color={TypographyColor.Tertiary}
>
{companyStageMap[opportunity.organization.stage]} •{' '}
{opportunity.organization.category}
</Typography>
<div className="flex flex-shrink flex-col flex-wrap">
<Typography
type={TypographyType.Body}
color={TypographyColor.Primary}
>
{opportunity.organization.name}
</Typography>
<Typography
type={TypographyType.Footnote}
color={TypographyColor.Tertiary}
>
{companyStageMap[opportunity.organization.stage]} •{' '}
{opportunity.organization.category}
</Typography>
</div>
</div>
</div>
)}

{/* SoMe Links */}
{opportunity.organization.socialLinks?.length > 0 && (
{opportunity.organization?.socialLinks?.length > 0 && (
<div className="flex gap-2 px-4">
{opportunity.organization.socialLinks.map(
({ link, socialType }) => (
Expand Down Expand Up @@ -786,7 +790,7 @@ const JobPage = (): ReactElement => {
Founded
</Typography>
<Typography type={TypographyType.Footnote} bold>
{opportunity.organization.founded}
{opportunity.organization?.founded || 'N/A'}
</Typography>

<Typography
Expand All @@ -796,7 +800,7 @@ const JobPage = (): ReactElement => {
HQ
</Typography>
<Typography type={TypographyType.Footnote} bold>
{opportunity.organization.location}
{opportunity.organization?.location || 'N/A'}
</Typography>

<Typography
Expand All @@ -806,13 +810,13 @@ const JobPage = (): ReactElement => {
Employees
</Typography>
<Typography type={TypographyType.Footnote} bold>
{companySizeMap[opportunity.organization.size]}
{companySizeMap[opportunity.organization?.size] || 'N/A'}
</Typography>
</div>
</SimpleTooltip>

{/* Description */}
{opportunity.organization.description && (
{!!opportunity.organization?.description && (
<SimpleTooltip
content={
canEdit ? labels.opportunity.companyInfoEditNotice : undefined
Expand All @@ -830,7 +834,7 @@ const JobPage = (): ReactElement => {
)}

{/* Perks & Benefits */}
{opportunity.organization.perks && (
{opportunity.organization?.perks?.length > 0 && (
<div className="flex flex-col gap-2 px-4">
<Typography bold type={TypographyType.Callout}>
Perks & Benefits
Expand Down