Skip to content

Commit 6a63733

Browse files
committed
feat: add DC v2
1 parent 9f0cedc commit 6a63733

36 files changed

Lines changed: 5779 additions & 1 deletion
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
import type { Meta, StoryObj } from '@storybook/react';
3+
import { action } from '@storybook/addon-actions';
4+
import { AddEpicModal } from './AddEpicModal';
5+
6+
const meta: Meta<typeof AddEpicModal> = {
7+
title: 'Digital Colleagues/AddEpicModal',
8+
component: AddEpicModal,
9+
parameters: {
10+
layout: 'centered',
11+
},
12+
argTypes: {
13+
isOpen: {
14+
control: 'boolean',
15+
description: 'Whether the modal is open',
16+
},
17+
onClose: {
18+
action: 'modal closed',
19+
description: 'Function called when modal is closed',
20+
},
21+
onAddEpic: {
22+
action: 'epic added',
23+
description: 'Function called when epic is added',
24+
},
25+
},
26+
};
27+
28+
export default meta;
29+
type Story = StoryObj<typeof AddEpicModal>;
30+
31+
export const Default: Story = {
32+
args: {
33+
isOpen: true,
34+
onClose: action('onClose'),
35+
onAddEpic: action('onAddEpic'),
36+
},
37+
};
38+
39+
export const Closed: Story = {
40+
args: {
41+
isOpen: false,
42+
onClose: action('onClose'),
43+
onAddEpic: action('onAddEpic'),
44+
},
45+
};
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
2+
import React, { useState } from 'react';
3+
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog';
4+
import { Button } from '@/components/ui/button';
5+
import { Input } from '@/components/ui/input';
6+
import { Textarea } from '@/components/ui/textarea';
7+
import { Label } from '@/components/ui/label';
8+
import { Epic } from './KanbanBoard';
9+
10+
interface AddEpicModalProps {
11+
isOpen: boolean;
12+
onClose: () => void;
13+
onAddEpic: (epic: Omit<Epic, 'id'>) => void;
14+
}
15+
16+
export const AddEpicModal: React.FC<AddEpicModalProps> = ({
17+
isOpen,
18+
onClose,
19+
onAddEpic,
20+
}) => {
21+
const [formData, setFormData] = useState({
22+
name: '',
23+
description: '',
24+
color: 'bg-blue-500',
25+
});
26+
27+
const colorOptions = [
28+
'bg-blue-500',
29+
'bg-green-500',
30+
'bg-purple-500',
31+
'bg-orange-500',
32+
'bg-red-500',
33+
'bg-yellow-500',
34+
'bg-pink-500',
35+
'bg-indigo-500',
36+
];
37+
38+
const handleSubmit = (e: React.FormEvent) => {
39+
e.preventDefault();
40+
if (formData.name.trim()) {
41+
onAddEpic({
42+
name: formData.name.trim(),
43+
description: formData.description.trim(),
44+
color: formData.color,
45+
});
46+
setFormData({
47+
name: '',
48+
description: '',
49+
color: 'bg-blue-500',
50+
});
51+
onClose();
52+
}
53+
};
54+
55+
const handleChange = (field: string, value: string) => {
56+
setFormData(prev => ({ ...prev, [field]: value }));
57+
};
58+
59+
return (
60+
<Dialog open={isOpen} onOpenChange={onClose}>
61+
<DialogContent className="sm:max-w-md">
62+
<DialogHeader>
63+
<DialogTitle>Add New Epic</DialogTitle>
64+
</DialogHeader>
65+
66+
<form onSubmit={handleSubmit} className="space-y-4">
67+
<div className="space-y-2">
68+
<Label htmlFor="name">Epic Name</Label>
69+
<Input
70+
id="name"
71+
value={formData.name}
72+
onChange={(e) => handleChange('name', e.target.value)}
73+
placeholder="Enter epic name"
74+
required
75+
/>
76+
</div>
77+
78+
<div className="space-y-2">
79+
<Label htmlFor="description">Description</Label>
80+
<Textarea
81+
id="description"
82+
value={formData.description}
83+
onChange={(e) => handleChange('description', e.target.value)}
84+
placeholder="Enter epic description (optional)"
85+
rows={3}
86+
/>
87+
</div>
88+
89+
<div className="space-y-2">
90+
<Label>Color</Label>
91+
<div className="flex gap-2 flex-wrap">
92+
{colorOptions.map(color => (
93+
<button
94+
key={color}
95+
type="button"
96+
onClick={() => handleChange('color', color)}
97+
className={`w-8 h-8 rounded-full ${color} ${
98+
formData.color === color ? 'ring-2 ring-gray-400' : ''
99+
}`}
100+
/>
101+
))}
102+
</div>
103+
</div>
104+
105+
<DialogFooter>
106+
<Button type="button" variant="outline" onClick={onClose}>
107+
Cancel
108+
</Button>
109+
<Button type="submit" className="bg-blue-600 hover:bg-blue-700">
110+
Add Epic
111+
</Button>
112+
</DialogFooter>
113+
</form>
114+
</DialogContent>
115+
</Dialog>
116+
);
117+
};
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
import type { Meta, StoryObj } from '@storybook/react';
3+
import { action } from '@storybook/addon-actions';
4+
import { AddTaskModal } from './AddTaskModal';
5+
6+
const mockEpics = [
7+
{ id: 'epic1', name: 'User Authentication', color: 'bg-blue-500', description: 'Secure login system' },
8+
{ id: 'epic2', name: 'Dashboard Features', color: 'bg-green-500', description: 'Dashboard functionality' },
9+
{ id: 'epic3', name: 'Mobile Optimization', color: 'bg-purple-500', description: 'Mobile responsive design' },
10+
];
11+
12+
const mockSprints = [
13+
{ id: 'backlog', name: 'Backlog', description: 'Tasks not assigned', startDate: new Date('2024-01-01'), endDate: new Date('2024-12-31'), isActive: false },
14+
{ id: 'sprint1', name: 'Sprint 1', description: 'Current sprint', startDate: new Date('2024-01-01'), endDate: new Date('2024-01-14'), isActive: true },
15+
{ id: 'sprint2', name: 'Sprint 2', description: 'Next sprint', startDate: new Date('2024-01-15'), endDate: new Date('2024-01-28'), isActive: false },
16+
];
17+
18+
const meta: Meta<typeof AddTaskModal> = {
19+
title: 'Digital Colleagues/AddTaskModal',
20+
component: AddTaskModal,
21+
parameters: {
22+
layout: 'centered',
23+
},
24+
argTypes: {
25+
isOpen: {
26+
control: 'boolean',
27+
description: 'Whether the modal is open',
28+
},
29+
onClose: {
30+
action: 'modal closed',
31+
description: 'Function called when modal is closed',
32+
},
33+
onAddTask: {
34+
action: 'task added',
35+
description: 'Function called when task is added',
36+
},
37+
},
38+
};
39+
40+
export default meta;
41+
type Story = StoryObj<typeof AddTaskModal>;
42+
43+
export const Default: Story = {
44+
args: {
45+
isOpen: true,
46+
epics: mockEpics,
47+
sprints: mockSprints,
48+
onClose: action('onClose'),
49+
onAddTask: action('onAddTask'),
50+
},
51+
};
52+
53+
export const WithManyEpics: Story = {
54+
args: {
55+
isOpen: true,
56+
epics: [
57+
...mockEpics,
58+
{ id: 'epic4', name: 'API Integration', color: 'bg-orange-500', description: 'Third-party APIs' },
59+
{ id: 'epic5', name: 'Performance', color: 'bg-red-500', description: 'Speed improvements' },
60+
{ id: 'epic6', name: 'Security', color: 'bg-yellow-500', description: 'Security enhancements' },
61+
],
62+
sprints: mockSprints,
63+
onClose: action('onClose'),
64+
onAddTask: action('onAddTask'),
65+
},
66+
};
67+
68+
export const WithManySprints: Story = {
69+
args: {
70+
isOpen: true,
71+
epics: mockEpics,
72+
sprints: [
73+
...mockSprints,
74+
{ id: 'sprint3', name: 'Sprint 3', description: 'Future sprint', startDate: new Date('2024-01-29'), endDate: new Date('2024-02-11'), isActive: false },
75+
{ id: 'sprint4', name: 'Sprint 4', description: 'Planning phase', startDate: new Date('2024-02-12'), endDate: new Date('2024-02-25'), isActive: false },
76+
],
77+
onClose: action('onClose'),
78+
onAddTask: action('onAddTask'),
79+
},
80+
};
81+
82+
export const Closed: Story = {
83+
args: {
84+
isOpen: false,
85+
epics: mockEpics,
86+
sprints: mockSprints,
87+
onClose: action('onClose'),
88+
onAddTask: action('onAddTask'),
89+
},
90+
};

0 commit comments

Comments
 (0)