Submission requirement modalg

feat/project
Kamran Ahmed 6 months ago
parent 08bc7795e4
commit d7e81bd13a
  1. 7
      src/components/Projects/StartProjectModal.tsx
  2. 32
      src/components/Projects/StatusStepper/ProjectStepper.tsx
  3. 31
      src/components/Projects/SubmissionRequirement.tsx
  4. 60
      src/components/Projects/SubmitProjectModal.tsx

@ -38,13 +38,6 @@ export function StartProjectModal(props: StartProjectModalProps) {
const projectUrl = `${import.meta.env.PUBLIC_APP_URL}/projects/${projectId}`;
const projectTips = [
'Create a repository on GitHub',
'Complete the task and push it to GitHub',
'Add a readme file with instructions on how to run the project',
'Submit your project once you are done to get feedback from the community',
];
const formattedStartedAt = startedAt ? getRelativeTimeString(startedAt) : '';
async function handleStartProject() {

@ -5,12 +5,12 @@ import { useStickyStuck } from '../../../hooks/use-sticky-stuck.tsx';
import { StepperAction } from './StepperAction.tsx';
import { StepperStepSeparator } from './StepperStepSeparator.tsx';
import { MilestoneStep } from './MilestoneStep.tsx';
import { httpGet, httpPost } from '../../../lib/http.ts';
import { httpGet } from '../../../lib/http.ts';
import { StartProjectModal } from '../StartProjectModal.tsx';
import { pageProgressMessage } from '../../../stores/page.ts';
import { getRelativeTimeString } from '../../../lib/date.ts';
import { isLoggedIn } from '../../../lib/jwt.ts';
import { showLoginPopup } from '../../../lib/popup.ts';
import { SubmitProjectModal } from '../SubmitProjectModal.tsx';
type ProjectStatusResponse = {
id?: string;
@ -34,6 +34,8 @@ export function ProjectStepper(props: ProjectStepperProps) {
const isSticky = useStickyStuck(stickyElRef, 8);
const [isStartingProject, setIsStartingProject] = useState(false);
const [isSubmittingProject, setIsSubmittingProject] = useState(false);
const [error, setError] = useState<string | null>(null);
const [activeStep, setActiveStep] = useState<number>(0);
const [isLoadingStatus, setIsLoadingStatus] = useState(true);
@ -86,6 +88,24 @@ export function ProjectStepper(props: ProjectStepperProps) {
},
)}
>
{isSubmittingProject && (
<SubmitProjectModal
onClose={() => setIsSubmittingProject(false)}
projectId={projectId}
onSubmit={(response) => {
const { repositoryUrl, submittedAt } = response;
setProjectStatus({
...projectStatus,
repositoryUrl,
submittedAt,
});
setActiveStep(2);
}}
repositoryUrl={projectStatus.repositoryUrl}
/>
)}
{isStartingProject && (
<StartProjectModal
projectId={projectId}
@ -169,6 +189,14 @@ export function ProjectStepper(props: ProjectStepperProps) {
isActive={activeStep === 1}
isCompleted={activeStep > 1}
icon={Send}
onClick={() => {
if (!isLoggedIn()) {
showLoginPopup();
return;
}
setIsSubmittingProject(true);
}}
text={activeStep > 1 ? 'Submitted' : 'Submit Solution'}
number={2}
/>

@ -0,0 +1,31 @@
import type { ReactNode } from 'react';
import { cn } from '../../lib/classname.ts';
import { CheckIcon, CircleDashed } from 'lucide-react';
type SubmissionRequirementProps = {
status: 'pending' | 'success' | 'error';
children: ReactNode;
};
export function SubmissionRequirement(props: SubmissionRequirementProps) {
const { status, children } = props;
return (
<div
className={cn(`flex items-center rounded-lg p-2 text-sm text-gray-900`, {
'bg-gray-200': status === 'pending',
'bg-green-200': status === 'success',
'bg-red-200': status === 'error',
})}
>
{status === 'pending' ? (
<CircleDashed className="h-4 w-4 text-gray-400" />
) : status === 'success' ? (
<CheckIcon className="h-4 w-4 text-green-800" />
) : (
<CheckIcon className="h-4 w-4 text-yellow-800" />
)}
<span className="ml-2">{children}</span>
</div>
);
}

@ -1,8 +1,11 @@
import { X } from 'lucide-react';
import { CheckIcon, CircleDashed, X } from 'lucide-react';
import { Modal } from '../Modal';
import { useState, type FormEvent } from 'react';
import { useState, type FormEvent, type ReactNode } from 'react';
import { useToast } from '../../hooks/use-toast';
import { httpPost } from '../../lib/http';
import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';
import { cn } from '../../lib/classname.ts';
import { SubmissionRequirement } from './SubmissionRequirement.tsx';
type SubmitProjectResponse = {
repositoryUrl: string;
@ -36,6 +39,10 @@ export function SubmitProjectModal(props: SubmitProjectModalProps) {
setError('');
setSuccessMessage('');
if (!repoUrl) {
throw new Error('Repository URL is required');
}
const repoUrlParts = repoUrl
.replace(/https?:\/\/(www\.)?github\.com/, '')
.split('/');
@ -51,9 +58,10 @@ export function SubmitProjectModal(props: SubmitProjectModalProps) {
const allContentsUrl = `${mainApiUrl}/contents`;
const allContentsResponse = await fetch(allContentsUrl);
if (!allContentsResponse.ok) {
const errorData = await allContentsResponse.json();
if (errorData?.status === 404) {
throw new Error('Repository not found');
if (allContentsResponse?.status === 404) {
throw new Error(
'Repository not found. Make sure it exists and is public.',
);
}
throw new Error('Failed to fetch repository contents');
@ -108,21 +116,47 @@ export function SubmitProjectModal(props: SubmitProjectModalProps) {
}
};
const verificationChecks = {
valid_url: {
status: 'pending',
message: 'URL must point to a public GitHub repository',
},
valid_repo: {
status: 'pending',
message: 'Repository must contain a readme file',
},
valid_readme: {
status: 'pending',
message: 'Readme file must contain the project URL',
},
};
return (
<Modal onClose={onClose} bodyClassName="h-auto p-4">
<h2 className="mb-0.5 text-xl font-semibold">
Submit Link to the GitHub repository
<h2 className="mb-2 flex items-center gap-2.5 text-2xl font-semibold">
<GitHubIcon className="h-6 w-6 text-black" /> Submit Solution URL
</h2>
<p className="text-balance text-sm text-gray-500">
Make sure to have a readme file in your project repository containing
the link to this project page.
<p className="text-sm text-gray-500">
Submit the URL of your GitHub repository with the solution.
</p>
<div className="my-4 flex flex-col gap-1">
<SubmissionRequirement status="pending">
URL must point to a public GitHub repository
</SubmissionRequirement>
<SubmissionRequirement status="pending">
Repository must contain a README file
</SubmissionRequirement>
<SubmissionRequirement status="pending">
README file must contain the project URL
</SubmissionRequirement>
</div>
<form className="mt-4" onSubmit={handleSubmit}>
<input
type="text"
className="w-full rounded-lg border border-gray-300 p-2 focus:border-gray-500 focus:outline-none"
placeholder="https://github.com/kamranahmedse/developer-roadmap"
className="w-full rounded-lg border border-gray-300 p-2 focus:border-gray-500 focus:outline-none text-sm"
placeholder="https://github.com/you/solution-repo"
value={repoUrl}
onChange={(e) => setRepoUrl(e.target.value)}
/>
@ -142,7 +176,7 @@ export function SubmitProjectModal(props: SubmitProjectModalProps) {
className="mt-2 w-full rounded-lg bg-black p-2 font-medium text-white disabled:opacity-50"
disabled={isLoading}
>
{isLoading ? 'Verifying...' : 'Verify'}
{isLoading ? 'Verifying...' : 'Verify Submission'}
</button>
</form>

Loading…
Cancel
Save