diff --git a/src/components/OpenSourceStat.astro b/src/components/OpenSourceStat.astro
index a7eee8ed1..97cf0bd95 100644
--- a/src/components/OpenSourceStat.astro
+++ b/src/components/OpenSourceStat.astro
@@ -44,7 +44,7 @@ const isDiscordMembers = text.toLowerCase() === 'discord members';
}
{value}
diff --git a/src/components/Projects/StartProjectModal.tsx b/src/components/Projects/StartProjectModal.tsx
index b6a30bf78..b9d6a6294 100644
--- a/src/components/Projects/StartProjectModal.tsx
+++ b/src/components/Projects/StartProjectModal.tsx
@@ -1,57 +1,175 @@
-import { X } from 'lucide-react';
+import {
+ Check,
+ CheckCircle,
+ CheckCircle2,
+ CopyCheck,
+ CopyIcon,
+ ServerCrash,
+ X,
+} from 'lucide-react';
import { Modal } from '../Modal';
import { getRelativeTimeString } from '../../lib/date';
+import { useEffect, useState } from 'react';
+import { Spinner } from '../ReactIcons/Spinner.tsx';
+import { httpPost } from '../../lib/http.ts';
+import { ErrorIcon } from '../ReactIcons/ErrorIcon.tsx';
+import { CheckIcon } from '../ReactIcons/CheckIcon.tsx';
+import { useCopyText } from '../../hooks/use-copy-text.ts';
+
+type StepLabelProps = {
+ label: string;
+};
+
+function StepLabel(props: StepLabelProps) {
+ const { label } = props;
+
+ return (
+
+ {label}
+
+ );
+}
type StartProjectModalProps = {
+ projectId: string;
onClose: () => void;
startedAt?: Date;
+ onStarted: (startedAt: Date) => void;
};
export function StartProjectModal(props: StartProjectModalProps) {
- const { onClose, startedAt } = props;
+ const { onClose, startedAt, onStarted, projectId } = props;
+
+ const [isStartingProject, setIsStartingProject] = useState(true);
+ const [error, setError] = useState
();
+
+ const { isCopied, copyText } = useCopyText();
+
+ const projectUrl = `${import.meta.env.PUBLIC_APP_URL}/projects/${projectId}`;
const projectTips = [
'Create a repository on GitHub',
- 'Develop the required functionality',
- 'Add a readme and make sure to link to the project page',
- 'Once you are done, make sure to come back and submit your solution to get feedback from others.',
- 'Feel free to join our discord and ask for help if you get stuck.',
+ '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() {
+ if (!projectId || startedAt) {
+ return;
+ }
+
+ setIsStartingProject(true);
+ const { response, error } = await httpPost<{
+ startedAt: Date;
+ }>(`${import.meta.env.PUBLIC_API_URL}/v1-start-project/${projectId}`, {});
+
+ if (error || !response) {
+ setError(error?.message || 'Failed to start project');
+ setIsStartingProject(false);
+ return;
+ }
+
+ onStarted(response.startedAt);
+ }
+
+ useEffect(() => {
+ handleStartProject().finally(() => setIsStartingProject(false));
+ }, []);
+
+ if (error) {
+ return (
+
+
+
+ );
+ }
+
+ if (isStartingProject) {
+ return (
+
+
+
+
Starting project ..
+
+
+ );
+ }
+
return (
-
-
- Started working...
- {formattedStartedAt ? (
-
- {formattedStartedAt}
-
- ) : null}
+
+
+
+ Project started{' '}
+ {formattedStartedAt}
+
+
+ Start Building
-
- You have started working on the project. Here are some tips to get most
- out of it.
+
+ Follow these steps to complete the project.
-
- {projectTips.map((tip) => {
- return (
- -
- {tip}
-
- );
- })}
-
+
+
+
+
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. Make
+ sure to include the{' '}
+ {' '}
+ in the readme file.
+
+
+
+
+
+ Submit your repository URL to help others learn and get feedback
+ from the community.
+
+
+
- Happy coding!
+
+
If you get stuck, you can always ask for help in the community chat on discord.
+
);
diff --git a/src/components/Projects/StatusStepper/ProjectStepper.tsx b/src/components/Projects/StatusStepper/ProjectStepper.tsx
index 8bb0f7e54..130b8fa64 100644
--- a/src/components/Projects/StatusStepper/ProjectStepper.tsx
+++ b/src/components/Projects/StatusStepper/ProjectStepper.tsx
@@ -5,7 +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 } from '../../../lib/http.ts';
+import { httpGet, httpPost } 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';
type ProjectStatusResponse = {
id?: string;
@@ -28,6 +33,7 @@ export function ProjectStepper(props: ProjectStepperProps) {
const stickyElRef = useRef(null);
const isSticky = useStickyStuck(stickyElRef, 8);
+ const [isStartingProject, setIsStartingProject] = useState(false);
const [error, setError] = useState(null);
const [activeStep, setActiveStep] = useState(0);
const [isLoadingStatus, setIsLoadingStatus] = useState(true);
@@ -80,6 +86,26 @@ export function ProjectStepper(props: ProjectStepperProps) {
},
)}
>
+ {isStartingProject && (
+ {
+ setProjectStatus({
+ ...projectStatus,
+ startedAt,
+ });
+ setActiveStep(1);
+ }}
+ startedAt={projectStatus?.startedAt}
+ onClose={() => setIsStartingProject(false)}
+ />
+ )}
+
+ {error && (
+
+ {error}
+
+ )}
{isLoadingStatus && (
)}
@@ -91,7 +117,35 @@ export function ProjectStepper(props: ProjectStepperProps) {
},
)}
>
- Start building, submit solution and get feedback from the community.
+ {activeStep === 0 && (
+ <>
+ Start building, submit solution and get feedback from the community.
+ >
+ )}
+ {activeStep === 1 && (
+ <>
+ Started working{' '}
+
+ {getRelativeTimeString(projectStatus.startedAt!)}
+
+ . Follow{' '}
+ {' '}
+ to get most out of it.
+ >
+ )}
@@ -101,6 +155,14 @@ export function ProjectStepper(props: ProjectStepperProps) {
icon={Play}
text={activeStep > 0 ? 'Started Working' : 'Start Working'}
number={1}
+ onClick={() => {
+ if (!isLoggedIn()) {
+ showLoginPopup();
+ return;
+ }
+
+ setIsStartingProject(true);
+ }}
/>
0} />