diff --git a/src/apps/copilots/src/pages/copilot-opportunity-details/apply-opportunity-modal/ApplyOpportunityModal.tsx b/src/apps/copilots/src/pages/copilot-opportunity-details/apply-opportunity-modal/ApplyOpportunityModal.tsx index 48fd2f364..ed355f305 100644 --- a/src/apps/copilots/src/pages/copilot-opportunity-details/apply-opportunity-modal/ApplyOpportunityModal.tsx +++ b/src/apps/copilots/src/pages/copilot-opportunity-details/apply-opportunity-modal/ApplyOpportunityModal.tsx @@ -17,17 +17,19 @@ interface ApplyOpportunityModalProps { const ApplyOpportunityModal: FC = props => { const [notes, setNotes] = useState('') const [success, setSuccess] = useState(false) + const [error, setError] = useState('') const onApply = useCallback(async () => { try { - await applyCopilotOpportunity(props.copilotOpportunityId, { + await applyCopilotOpportunity(props.copilotOpportunityId, notes ? { notes, - }) + } : undefined) props.onApplied() setSuccess(true) - } catch (e) { - setSuccess(true) + } catch (e: any) { + setSuccess(false) + setError(e.message) } }, [props.copilotOpportunityId, notes]) @@ -77,6 +79,8 @@ const ApplyOpportunityModal: FC = props => { name='Notes' onChange={onChange} value={notes} + error={error} + dirty={!!error} /> ) } diff --git a/src/apps/copilots/src/pages/copilot-opportunity-details/index.tsx b/src/apps/copilots/src/pages/copilot-opportunity-details/index.tsx index 21b4c8807..dae460eed 100644 --- a/src/apps/copilots/src/pages/copilot-opportunity-details/index.tsx +++ b/src/apps/copilots/src/pages/copilot-opportunity-details/index.tsx @@ -18,11 +18,13 @@ import { ButtonProps, ContentLayout, IconOutline, + IconSolid, LoadingSpinner, PageTitle, TabsNavbar, } from '~/libs/ui' import { profileContext, ProfileContextData, UserRole } from '~/libs/core' +import { textFormatDateLocaleShortString } from '~/libs/shared' import { CopilotApplication } from '../../models/CopilotApplication' import { @@ -77,8 +79,12 @@ const CopilotOpportunityDetails: FC<{}> = () => { const [activeTab, setActiveTab]: [string, Dispatch>] = useState(activeTabHash) useEffect(() => { - setActiveTab(activeTabHash) - }, [activeTabHash]) + if (isAdminOrPM) { + setActiveTab(activeTabHash) + } else { + setActiveTab('0') + } + }, [activeTabHash, isAdminOrPM]) const handleTabChange = useCallback((tabId: string): void => { setActiveTab(tabId) @@ -97,6 +103,7 @@ const CopilotOpportunityDetails: FC<{}> = () => { const onApplied: () => void = useCallback(() => { mutate(`${copilotBaseUrl}/copilots/opportunity/${opportunityId}/applications`) + mutate(`${copilotBaseUrl}/copilots/opportunity/${opportunityId}`) }, []) const onCloseApplyModal: () => void = useCallback(() => { @@ -117,16 +124,34 @@ const CopilotOpportunityDetails: FC<{}> = () => { onClick: () => setShowApplyOpportunityModal(true), } + const application = copilotApplications && copilotApplications[0] + return ( + + + {`Applied on ${textFormatDateLocaleShortString(new Date(application.createdAt))}`} + + + )} > - Copilot Opportunity + + Copilot Opportunity + {isValidating && !showNotFound && ( ) } diff --git a/src/apps/copilots/src/pages/copilot-opportunity-details/styles.module.scss b/src/apps/copilots/src/pages/copilot-opportunity-details/styles.module.scss index 9b28a7018..8bb4b5162 100644 --- a/src/apps/copilots/src/pages/copilot-opportunity-details/styles.module.scss +++ b/src/apps/copilots/src/pages/copilot-opportunity-details/styles.module.scss @@ -54,6 +54,22 @@ color: $teal-100; } +.applied { + display: flex; + align-items: center; + .appliedIcon { + width: 30px; + height: 30px; + color: $green-1; + } + + .appliedText { + font-size: 14px; + font-weight: 600; + color: #333; + } +} + .textCaps { text-transform: capitalize; } \ No newline at end of file diff --git a/src/apps/copilots/src/services/copilot-opportunities.ts b/src/apps/copilots/src/services/copilot-opportunities.ts index 76589f443..d5e8f7f19 100644 --- a/src/apps/copilots/src/services/copilot-opportunities.ts +++ b/src/apps/copilots/src/services/copilot-opportunities.ts @@ -97,7 +97,7 @@ export const useCopilotOpportunity = (opportunityId?: string): CopilotOpportunit * @param request * @returns */ -export const applyCopilotOpportunity = async (opportunityId: number, request: { +export const applyCopilotOpportunity = async (opportunityId: number, request?: { notes?: string; }): Promise => { const url = `${copilotBaseUrl}/copilots/opportunity/${opportunityId}/apply` diff --git a/src/libs/ui/lib/components/content-layout/ContentLayout.tsx b/src/libs/ui/lib/components/content-layout/ContentLayout.tsx index 7eb87a870..561400e51 100644 --- a/src/libs/ui/lib/components/content-layout/ContentLayout.tsx +++ b/src/libs/ui/lib/components/content-layout/ContentLayout.tsx @@ -14,6 +14,7 @@ export interface ContentLayoutProps { outerClass?: string title?: string titleClass?: string + infoComponent?: ReactNode } const ContentLayout: FC = (props: ContentLayoutProps) => ( @@ -50,6 +51,12 @@ const ContentLayout: FC = (props: ContentLayoutProps) => ( )} + {!!props.infoComponent && ( +
+ {props.infoComponent} +
+ )} + )} diff --git a/src/libs/ui/lib/styles/_modals.scss b/src/libs/ui/lib/styles/_modals.scss index 13eedcc8a..902a8b95a 100644 --- a/src/libs/ui/lib/styles/_modals.scss +++ b/src/libs/ui/lib/styles/_modals.scss @@ -54,7 +54,6 @@ .react-responsive-modal-closeButton { top: $sp-5; - padding: $sp-1; border-radius: 50%; svg {