Skip to content

Commit 31fdaeb

Browse files
committed
fix: applies fix on project form and index view
1 parent 302edf9 commit 31fdaeb

3 files changed

Lines changed: 118 additions & 89 deletions

File tree

src/components/Foundary/types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,3 +1063,14 @@ export interface Notification {
10631063
actionLabel?: string
10641064
onAction?: () => void
10651065
}
1066+
1067+
export interface ProjectFormData {
1068+
name: string
1069+
objectives: string
1070+
workInstructions: string
1071+
plan: boolean
1072+
}
1073+
1074+
export interface ProjectCreationData extends ProjectFormData {
1075+
description?: string
1076+
}
Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
1-
"use client"
1+
'use client'
22

3-
import { useState } from "react"
4-
import { motion, AnimatePresence } from "motion/react"
5-
import { DigitalColleageusLayout } from "../DigitalColleagues/DigitalColleageusLayout"
6-
import { DashboardHero } from "../Heros/DashboardHero/DashboardHero"
7-
import { AppCard } from "../.archive/app-card"
8-
import { FileList } from "./file-list"
9-
import { ProjectCard } from "./project-card"
10-
import { ProjectForm } from "./project-form"
3+
import { useState } from 'react'
4+
import { motion, AnimatePresence } from 'motion/react'
5+
import { DashboardHero } from '../Heros/DashboardHero/DashboardHero'
6+
import { ProjectCard } from './project-card'
7+
import { ProjectForm } from './project-form'
118
import {
129
Dialog,
1310
DialogContent,
1411
DialogDescription,
1512
DialogHeader,
1613
DialogTitle,
17-
DialogTrigger,
18-
} from "@/components/ui/dialog"
14+
} from '@/components/ui/dialog'
1915

20-
import type { App, RecentFile, ProjectSummary, Project, ProjectFormData } from "../DigitalColleagues/types"
21-
// import { ColleaguesManagement } from "../colleagues-management"
16+
import type { ProjectSummary, ProjectFormData, ProjectCreationData } from '../Foundary/types'
2217

2318
const AnimatedCircles = () => (
2419
<motion.div
2520
animate={{ rotate: 360 }}
26-
transition={{ duration: 50, repeat: Number.POSITIVE_INFINITY, ease: "linear" }}
21+
transition={{ duration: 50, repeat: Number.POSITIVE_INFINITY, ease: 'linear' }}
2722
className="relative h-40 w-40"
2823
>
2924
<div className="absolute inset-0 rounded-full bg-white/10 backdrop-blur-md" />
@@ -35,14 +30,18 @@ const AnimatedCircles = () => (
3530
)
3631

3732
interface HomeProps {
38-
projects?: ProjectSummary[];
39-
onAddProject: (project: ProjectFormData) => void;
40-
handleProjectOpen: (project: ProjectSummary) => void;
41-
handleProjectShare: (project: ProjectSummary) => void;
33+
projects?: ProjectSummary[]
34+
onAddProject: (project: ProjectCreationData) => Promise<void>
35+
handleProjectOpen: (project: ProjectSummary) => void
36+
handleProjectShare: (project: ProjectSummary) => void
4237
}
4338

44-
export default function Home({ projects=[], onAddProject, handleProjectOpen, handleProjectShare
45-
}: HomeProps) {
39+
export default function Home({
40+
projects = [],
41+
onAddProject,
42+
handleProjectOpen,
43+
handleProjectShare,
44+
}: HomeProps) {
4645
const [isNewProjectDialogOpen, setIsNewProjectDialogOpen] = useState(false)
4746
const [isSubmitting, setIsSubmitting] = useState(false)
4847

@@ -63,8 +62,7 @@ export default function Home({ projects=[], onAddProject, handleProjectOpen, h
6362
}
6463

6564
return (
66-
<div className="px-2 md:px-4 py-4 space-y-8">
67-
65+
<div className="px-2 md:px-4 py-4 space-y-8">
6866
<AnimatePresence mode="wait">
6967
<motion.div
7068
key="projects-index-view"
@@ -73,29 +71,29 @@ export default function Home({ projects=[], onAddProject, handleProjectOpen, h
7371
exit={{ opacity: 0, y: -10 }}
7472
transition={{ duration: 0.2 }}
7573
>
76-
<DashboardHero
77-
title="Project Management"
78-
description="Organise your work into projects to collaborate with your team."
79-
gradient="bg-gradient-to-r from-purple-600 via-violet-600 to-indigo-600"
80-
primaryAction={{
81-
label: "New Project",
82-
onClick: handleNewProjectClick,
83-
}}
84-
/>
74+
<DashboardHero
75+
title="Project Management"
76+
description="Organize your work into projects to collaborate with your team."
77+
gradient="bg-gradient-to-r from-purple-600 via-violet-600 to-indigo-600"
78+
primaryAction={{
79+
label: 'New Project',
80+
onClick: handleNewProjectClick,
81+
}}
82+
/>
8583

86-
<section className="space-y-4 mt-8">
87-
<h2 className="text-2xl font-semibold">Active Projects</h2>
88-
<div className="grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
89-
{projects.map((project) => (
90-
<ProjectCard
91-
key={project.name}
92-
project={project}
93-
onOpen={handleProjectOpen}
94-
onShare={handleProjectShare}
95-
/>
96-
))}
97-
</div>
98-
</section>
84+
<section className="space-y-4 mt-8">
85+
<h2 className="text-2xl font-semibold">Active Projects</h2>
86+
<div className="grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
87+
{projects.map((project) => (
88+
<ProjectCard
89+
key={project.id}
90+
project={project}
91+
onOpen={handleProjectOpen}
92+
onShare={handleProjectShare}
93+
/>
94+
))}
95+
</div>
96+
</section>
9997
</motion.div>
10098
</AnimatePresence>
10199

@@ -104,9 +102,7 @@ export default function Home({ projects=[], onAddProject, handleProjectOpen, h
104102
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">
105103
<DialogHeader className="sr-only">
106104
<DialogTitle>Create New Project</DialogTitle>
107-
<DialogDescription>
108-
Fill out the form below to create a new project.
109-
</DialogDescription>
105+
<DialogDescription>Fill out the form below to create a new project.</DialogDescription>
110106
</DialogHeader>
111107
<ProjectForm
112108
onSubmit={handleCreateProject}
@@ -116,7 +112,6 @@ export default function Home({ projects=[], onAddProject, handleProjectOpen, h
116112
/>
117113
</DialogContent>
118114
</Dialog>
119-
</div>
120-
115+
</div>
121116
)
122117
}

src/components/Projects/project-form.tsx

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import { Input } from '@/components/ui/input'
66
import { Textarea } from '@/components/ui/textarea'
77
import { Checkbox } from '@/components/ui/checkbox'
88
import { Label } from '@/components/ui/label'
9-
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
10-
import { ProjectFormData } from '../DigitalColleagues/types'
9+
10+
import { ProjectCreationData } from '../DigitalColleagues/types'
1111
import { Loader2, Plus, X } from 'lucide-react'
1212

1313
interface ProjectFormProps {
14-
onSubmit: (data: ProjectFormData) => void | Promise<void>
14+
onSubmit: (data: ProjectCreationData) => void | Promise<void>
1515
onCancel?: () => void
1616
isLoading?: boolean
17-
initialData?: Partial<ProjectFormData>
17+
initialData?: Partial<ProjectCreationData>
1818
className?: string
1919
}
2020

@@ -23,19 +23,20 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
2323
onCancel,
2424
isLoading = false,
2525
initialData,
26-
className = ''
26+
className = '',
2727
}) => {
28-
const [formData, setFormData] = useState<ProjectFormData>({
28+
const [formData, setFormData] = useState<ProjectCreationData>({
2929
name: initialData?.name || '',
30+
description: initialData?.description || '',
3031
objectives: initialData?.objectives || '',
3132
workInstructions: initialData?.workInstructions || '',
32-
plan: initialData?.plan || false
33+
plan: initialData?.plan || false,
3334
})
3435

35-
const [errors, setErrors] = useState<Partial<Record<keyof ProjectFormData, string>>>({})
36+
const [errors, setErrors] = useState<Partial<Record<keyof ProjectCreationData, string>>>({})
3637

3738
const validateForm = (): boolean => {
38-
const newErrors: Partial<Record<keyof ProjectFormData, string>> = {}
39+
const newErrors: Partial<Record<keyof ProjectCreationData, string>> = {}
3940

4041
if (!formData.name.trim()) {
4142
newErrors.name = 'Project name is required'
@@ -52,7 +53,8 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
5253
if (!formData.workInstructions.trim()) {
5354
newErrors.workInstructions = 'Work instructions are required'
5455
} else if (formData.workInstructions.trim().length < 20) {
55-
newErrors.workInstructions = 'Please provide more detailed work instructions (at least 20 characters)'
56+
newErrors.workInstructions =
57+
'Please provide more detailed work instructions (at least 20 characters)'
5658
}
5759

5860
setErrors(newErrors)
@@ -61,7 +63,7 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
6163

6264
const handleSubmit = async (e: React.FormEvent) => {
6365
e.preventDefault()
64-
66+
6567
if (!validateForm()) {
6668
return
6769
}
@@ -73,29 +75,30 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
7375
}
7476
}
7577

76-
const handleInputChange = (field: keyof ProjectFormData, value: string | boolean) => {
77-
setFormData(prev => ({ ...prev, [field]: value }))
78-
78+
const handleInputChange = (field: keyof ProjectCreationData, value: string | boolean) => {
79+
setFormData((prev) => ({ ...prev, [field]: value }))
80+
7981
// Clear error when user starts typing
8082
if (errors[field]) {
81-
setErrors(prev => ({ ...prev, [field]: undefined }))
83+
setErrors((prev) => ({ ...prev, [field]: undefined }))
8284
}
8385
}
8486

8587
return (
86-
<Card className={`w-full max-w-2xl ${className}`}>
87-
<CardHeader>
88-
<CardTitle className="flex items-center gap-2">
88+
<div className={`w-full max-w-2xl ${className}`}>
89+
<div className="mb-4">
90+
<div className="flex items-center gap-2">
8991
<Plus className="h-5 w-5" />
9092
Create New Project
91-
</CardTitle>
92-
<CardDescription>
93-
Set up a new project with clear objectives and work instructions to help your team collaborate effectively.
94-
</CardDescription>
95-
</CardHeader>
93+
</div>
94+
<p className="text-sm text-gray-500">
95+
Set up a new project with clear objectives and work instructions to help your team
96+
collaborate effectively.
97+
</p>
98+
</div>
9699

97100
<form onSubmit={handleSubmit}>
98-
<CardContent className="space-y-6">
101+
<div className="space-y-6">
99102
{/* Project Name */}
100103
<div className="space-y-2">
101104
<Label htmlFor="name" className="text-sm font-medium">
@@ -111,9 +114,23 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
111114
disabled={isLoading}
112115
maxLength={100}
113116
/>
114-
{errors.name && (
115-
<p className="text-sm text-red-600">{errors.name}</p>
116-
)}
117+
{errors.name && <p className="text-sm text-red-600">{errors.name}</p>}
118+
</div>
119+
<div className="space-y-2">
120+
<Label htmlFor="name" className="text-sm font-medium">
121+
Project Description *
122+
</Label>
123+
<Input
124+
id="description"
125+
type="text"
126+
placeholder="Enter project description"
127+
value={formData.description}
128+
onChange={(e) => handleInputChange('description', e.target.value)}
129+
className={errors.description ? 'border-red-500 focus:border-red-500' : ''}
130+
disabled={isLoading}
131+
maxLength={100}
132+
/>
133+
{errors.description && <p className="text-sm text-red-600">{errors.description}</p>}
117134
</div>
118135

119136
{/* Project Objectives */}
@@ -126,12 +143,16 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
126143
placeholder="Describe the main goals and objectives of this project..."
127144
value={formData.objectives}
128145
onChange={(e) => handleInputChange('objectives', e.target.value)}
129-
className={`min-h-[100px] resize-y ${errors.objectives ? 'border-red-500 focus:border-red-500' : ''}`}
146+
className={`min-h-[100px] resize-y ${
147+
errors.objectives ? 'border-red-500 focus:border-red-500' : ''
148+
}`}
130149
disabled={isLoading}
131150
maxLength={1000}
132151
/>
133152
<div className="flex justify-between text-xs text-gray-500">
134-
<span>{errors.objectives && <span className="text-red-600">{errors.objectives}</span>}</span>
153+
<span>
154+
{errors.objectives && <span className="text-red-600">{errors.objectives}</span>}
155+
</span>
135156
<span>{formData.objectives.length}/1000</span>
136157
</div>
137158
</div>
@@ -146,12 +167,18 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
146167
placeholder="Provide detailed instructions on how the work should be carried out, including processes, standards, and expectations..."
147168
value={formData.workInstructions}
148169
onChange={(e) => handleInputChange('workInstructions', e.target.value)}
149-
className={`min-h-[120px] resize-y ${errors.workInstructions ? 'border-red-500 focus:border-red-500' : ''}`}
170+
className={`min-h-[120px] resize-y ${
171+
errors.workInstructions ? 'border-red-500 focus:border-red-500' : ''
172+
}`}
150173
disabled={isLoading}
151174
maxLength={2000}
152175
/>
153176
<div className="flex justify-between text-xs text-gray-500">
154-
<span>{errors.workInstructions && <span className="text-red-600">{errors.workInstructions}</span>}</span>
177+
<span>
178+
{errors.workInstructions && (
179+
<span className="text-red-600">{errors.workInstructions}</span>
180+
)}
181+
</span>
155182
<span>{formData.workInstructions.length}/2000</span>
156183
</div>
157184
</div>
@@ -174,9 +201,9 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
174201
This will allow project managers to create sprints, assign tasks, and track progress.
175202
</p>
176203
</div>
177-
</CardContent>
204+
</div>
178205

179-
<CardFooter className="flex justify-end gap-3">
206+
<div className="flex justify-end gap-3">
180207
{onCancel && (
181208
<Button
182209
type="button"
@@ -189,11 +216,7 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
189216
Cancel
190217
</Button>
191218
)}
192-
<Button
193-
type="submit"
194-
disabled={isLoading}
195-
className="flex items-center gap-2"
196-
>
219+
<Button type="submit" disabled={isLoading} className="flex items-center gap-2">
197220
{isLoading ? (
198221
<>
199222
<Loader2 className="h-4 w-4 animate-spin" />
@@ -206,9 +229,9 @@ export const ProjectForm: React.FC<ProjectFormProps> = ({
206229
</>
207230
)}
208231
</Button>
209-
</CardFooter>
232+
</div>
210233
</form>
211-
</Card>
234+
</div>
212235
)
213236
}
214237

0 commit comments

Comments
 (0)