pull/7791/head
Arik Chakma 1 week ago
parent b07a44470b
commit a9755a57ed
  1. 23
      src/components/CustomRoadmap/CreateRoadmap/CreateRoadmapModal.tsx
  2. 72
      src/components/CustomRoadmap/FeaturedListing/FeaturedListingStatus.tsx
  3. 12
      src/components/CustomRoadmap/RoadmapHeader.tsx
  4. 75
      src/components/CustomRoadmap/Showcase/ShowcaseAlert.tsx
  5. 42
      src/components/CustomRoadmap/Showcase/ShowcaseStatus.tsx
  6. 18
      src/components/CustomRoadmap/Showcase/SubmitShowcaseWarning.tsx

@ -23,21 +23,17 @@ export const allowedCustomRoadmapType = ['role', 'skill'] as const;
export type AllowedCustomRoadmapType =
(typeof allowedCustomRoadmapType)[number];
export const allowedShowcaseStatus = ['visible', 'hidden'] as const;
export type AllowedShowcaseStatus = (typeof allowedShowcaseStatus)[number];
export const allowedRoadmapFeaturedListStatus = [
export const allowedShowcaseStatus = [
'idle',
'submitted',
'approved',
'rejected',
'rejected_with_reason',
] as const;
export type AllowedRoadmapFeaturedListStatus =
(typeof allowedRoadmapFeaturedListStatus)[number];
export type AllowedShowcaseStatus = (typeof allowedShowcaseStatus)[number];
export interface RoadmapDocument {
_id?: string;
_id: string;
title: string;
description?: string;
slug?: string;
@ -61,18 +57,21 @@ export interface RoadmapDocument {
edges: any[];
isDiscoverable?: boolean;
showcaseStatus?: AllowedShowcaseStatus;
ratings: {
average: number;
totalCount: number;
breakdown: {
[key: number]: number;
};
};
featuredListStatus?: AllowedRoadmapFeaturedListStatus;
featuredListRejectedReason?: string;
featuredListSubmittedAt?: Date;
featuredListApprovedAt?: Date;
showcaseStatus?: AllowedShowcaseStatus;
showcaseRejectedReason?: string;
showcaseRejectedAt?: Date;
showcaseSubmittedAt?: Date;
showcaseApprovedAt?: Date;
hasMigratedContent?: boolean;
createdAt: Date;
updatedAt: Date;

@ -1,72 +0,0 @@
import { useState } from 'react';
import { SubmitFeaturedListingWarning } from './SubmitFeaturedListingWarning';
import type { GetRoadmapResponse } from '../CustomRoadmap';
import { CheckIcon, EyeIcon, FlagIcon, SendIcon, XIcon } from 'lucide-react';
import { cn } from '../../../lib/classname';
type FeaturedListingStatusProps = {
currentRoadmap: GetRoadmapResponse;
};
export function FeaturedListingStatus(props: FeaturedListingStatusProps) {
const { currentRoadmap } = props;
const { featuredListStatus = 'idle' } = currentRoadmap;
const [showSubmitWarning, setShowSubmitWarning] = useState(false);
const currentLabel = {
idle: {
icon: SendIcon,
label: 'Submit for Featured Listing',
className: 'bg-gray-100 text-gray-600 border-gray-200',
},
submitted: {
icon: EyeIcon,
label: 'Waiting for Approval',
className: 'bg-blue-100 text-blue-600 border-blue-200',
},
approved: {
icon: CheckIcon,
label: 'Approved',
className: 'bg-green-100 text-green-600 border-green-200',
},
rejected: {
icon: XIcon,
label: 'Rejected',
className: 'bg-red-100 text-red-600 border-red-200',
},
rejected_with_reason: {
icon: FlagIcon,
label: 'Changes Requested',
className: 'bg-yellow-100 text-yellow-600 border-yellow-200',
},
}[featuredListStatus];
return (
<>
{showSubmitWarning && (
<SubmitFeaturedListingWarning
onClose={() => {
setShowSubmitWarning(false);
}}
/>
)}
<button
className={cn(
'flex items-center gap-1.5 rounded-full border px-2 text-sm',
currentLabel?.className,
)}
onClick={() => {
setShowSubmitWarning(true);
}}
disabled={
!['idle', 'rejected_with_reason'].includes(featuredListStatus)
}
>
<currentLabel.icon className="size-3 stroke-[2.5]" />
{currentLabel.label}
</button>
</>
);
}

@ -11,7 +11,8 @@ import { RoadmapActionButton } from './RoadmapActionButton';
import { ShareRoadmapButton } from '../ShareRoadmapButton.tsx';
import { CustomRoadmapAlert } from './CustomRoadmapAlert.tsx';
import { CustomRoadmapRatings } from './CustomRoadmapRatings.tsx';
import { FeaturedListingStatus } from './FeaturedListing/FeaturedListingStatus.tsx';
import { ShowcaseStatus } from './Showcase/ShowcaseStatus.tsx';
import { ShowcaseAlert } from './Showcase/ShowcaseAlert.tsx';
type RoadmapHeaderProps = {};
@ -74,6 +75,9 @@ export function RoadmapHeader(props: RoadmapHeaderProps) {
: '/images/default-avatar.png';
return (
<>
{$currentRoadmap && <ShowcaseAlert currentRoadmap={$currentRoadmap} />}
<div className="border-b">
<div className="container relative py-5 sm:py-12">
{!$canManageCurrentRoadmap && <CustomRoadmapAlert />}
@ -152,7 +156,7 @@ export function RoadmapHeader(props: RoadmapHeaderProps) {
)}
{$currentRoadmap && (
<FeaturedListingStatus currentRoadmap={$currentRoadmap} />
<ShowcaseStatus currentRoadmap={$currentRoadmap} />
)}
<RoadmapActionButton
@ -177,7 +181,8 @@ export function RoadmapHeader(props: RoadmapHeaderProps) {
</>
)}
{((ratings?.average || 0) > 0 || showcaseStatus === 'visible') && (
{((ratings?.average || 0) > 0 ||
showcaseStatus === 'approved') && (
<CustomRoadmapRatings
roadmapSlug={roadmapSlug!}
ratings={ratings!}
@ -195,5 +200,6 @@ export function RoadmapHeader(props: RoadmapHeaderProps) {
/>
</div>
</div>
</>
);
}

@ -0,0 +1,75 @@
import {
CheckIcon,
EyeIcon,
FlagIcon,
FrownIcon,
SmileIcon,
XIcon,
} from 'lucide-react';
import { cn } from '../../../lib/classname';
import type { GetRoadmapResponse } from '../CustomRoadmap';
type ShowcaseAlertProps = {
currentRoadmap: GetRoadmapResponse;
};
export function ShowcaseAlert(props: ShowcaseAlertProps) {
const { currentRoadmap } = props;
// const { showcaseStatus = 'idle' } = currentRoadmap;
// if (showcaseStatus === 'idle') {
// return null;
// }
const showcaseStatus = 'rejected_with_reason';
const showcaseStatusMap = {
submitted: {
icon: EyeIcon,
label:
'We are reviewing your roadmap. It will be visible to everyone on the platform once approved.',
className: 'text-blue-600 border-blue-200',
},
approved: {
icon: SmileIcon,
label: 'Hooray! Your roadmap is now visible to everyone on the platform.',
className: 'text-green-600 border-green-200',
},
rejected: {
icon: FrownIcon,
label: 'Sorry, we are unable to feature your roadmap at this time.',
className: 'text-red-600 border-red-200',
},
rejected_with_reason: {
icon: FlagIcon,
label: (
<>
Your roadmap needs changes before it can be featured.{' '}
<button className="font-medium underline underline-offset-2 hover:no-underline">
Check Reason
</button>
</>
),
className: 'text-yellow-600 border-yellow-200',
},
};
const { icon: Icon, label, className } = showcaseStatusMap[showcaseStatus];
return (
<div
className={cn(
showcaseStatus === 'submitted' && 'bg-blue-100',
showcaseStatus === 'approved' && 'bg-green-100',
showcaseStatus === 'rejected' && 'bg-red-100',
showcaseStatus === 'rejected_with_reason' && 'bg-yellow-100',
)}
>
<div className="container relative flex items-center justify-center py-2 text-sm">
<div className={cn('flex items-center gap-2', className)}>
<Icon className="h-4 w-4 shrink-0 stroke-[2.5]" />
<div>{label}</div>
</div>
</div>
</div>
);
}

@ -0,0 +1,42 @@
import { useState } from 'react';
import { SubmitShowcaseWarning } from './SubmitShowcaseWarning';
import type { GetRoadmapResponse } from '../CustomRoadmap';
import { SendIcon } from 'lucide-react';
type ShowcaseStatusProps = {
currentRoadmap: GetRoadmapResponse;
};
export function ShowcaseStatus(props: ShowcaseStatusProps) {
const { currentRoadmap } = props;
const { showcaseStatus = 'idle' } = currentRoadmap;
const [showSubmitWarning, setShowSubmitWarning] = useState(false);
if (!currentRoadmap || showcaseStatus !== 'idle') {
return null;
}
return (
<>
{showSubmitWarning && (
<SubmitShowcaseWarning
onClose={() => {
setShowSubmitWarning(false);
}}
/>
)}
<button
className="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white py-1.5 pl-2 pr-2 text-xs font-medium text-black hover:border-gray-300 hover:bg-gray-300 sm:pl-1.5 sm:pr-3 sm:text-sm"
onClick={() => {
setShowSubmitWarning(true);
}}
disabled={showcaseStatus !== 'idle'}
>
<SendIcon className="mr-0 h-4 w-4 stroke-[2.5] sm:mr-1.5" />
<span className="hidden sm:inline">Submit for Showcase</span>
</button>
</>
);
}

@ -6,12 +6,12 @@ import { useStore } from '@nanostores/react';
import { currentRoadmap } from '../../../stores/roadmap';
import { useToast } from '../../../hooks/use-toast';
type SubmitFeaturedListingWarningProps = {
type SubmitShowcaseWarningProps = {
onClose: () => void;
};
export function SubmitFeaturedListingWarning(
props: SubmitFeaturedListingWarningProps,
export function SubmitShowcaseWarning(
props: SubmitShowcaseWarningProps,
) {
const { onClose } = props;
@ -40,21 +40,21 @@ export function SubmitFeaturedListingWarning(
queryClient,
);
const { featuredListStatus = 'idle', featuredListRejectedReason } =
const { showcaseStatus = 'idle', showcaseRejectedReason } =
$currentRoadmap || {};
return (
<Modal onClose={onClose}>
<div className="p-4">
<h2 className="text-lg font-semibold">
{featuredListStatus === 'rejected_with_reason'
{showcaseStatus === 'rejected_with_reason'
? 'Rejected Reason'
: 'Featured Listing'}
</h2>
<p className="mt-2 text-sm">
{featuredListStatus === 'rejected_with_reason' &&
featuredListRejectedReason}
{featuredListStatus === 'idle' && (
{showcaseStatus === 'rejected_with_reason' &&
showcaseRejectedReason}
{showcaseStatus === 'idle' && (
<>
Submitting your roadmap for a featured listing will make it
visible to everyone on the platform.{' '}
@ -78,7 +78,7 @@ export function SubmitFeaturedListingWarning(
>
{submit.isPending
? 'Submitting...'
: featuredListStatus === 'rejected_with_reason'
: showcaseStatus === 'rejected_with_reason'
? 'Resubmit'
: 'Submit'}
</button>
Loading…
Cancel
Save