create-mcp-use-app 0.2.2 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,408 +0,0 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { createRoot } from 'react-dom/client'
3
-
4
- interface Todo {
5
- id: string
6
- text: string
7
- completed: boolean
8
- priority: 'low' | 'medium' | 'high'
9
- dueDate?: string
10
- category?: string
11
- }
12
-
13
- interface TodoListProps {
14
- initialTodos?: Todo[]
15
- }
16
-
17
- const TodoList: React.FC<TodoListProps> = ({ initialTodos = [] }) => {
18
- const [todos, setTodos] = useState<Todo[]>(initialTodos)
19
- const [newTodo, setNewTodo] = useState('')
20
- const [filter, setFilter] = useState<'all' | 'active' | 'completed'>('all')
21
- const [sortBy, setSortBy] = useState<'priority' | 'dueDate' | 'created'>('priority')
22
-
23
- // Load todos from URL parameters or use defaults
24
- useEffect(() => {
25
- const urlParams = new URLSearchParams(window.location.search)
26
- const todosParam = urlParams.get('todos')
27
-
28
- if (todosParam) {
29
- try {
30
- const parsedTodos = JSON.parse(decodeURIComponent(todosParam))
31
- setTodos(parsedTodos)
32
- }
33
- catch (error) {
34
- console.error('Error parsing todos from URL:', error)
35
- }
36
- }
37
- else {
38
- // Default todos for demo
39
- setTodos([
40
- { id: '1', text: 'Complete project proposal', completed: false, priority: 'high', dueDate: '2024-01-15', category: 'Work' },
41
- { id: '2', text: 'Buy groceries', completed: false, priority: 'medium', dueDate: '2024-01-12', category: 'Personal' },
42
- { id: '3', text: 'Call dentist', completed: true, priority: 'low', category: 'Health' },
43
- { id: '4', text: 'Read React documentation', completed: false, priority: 'medium', category: 'Learning' },
44
- { id: '5', text: 'Plan weekend trip', completed: false, priority: 'low', dueDate: '2024-01-20', category: 'Personal' },
45
- ])
46
- }
47
- }, [])
48
-
49
- const addTodo = () => {
50
- if (newTodo.trim()) {
51
- const todo: Todo = {
52
- id: Date.now().toString(),
53
- text: newTodo,
54
- completed: false,
55
- priority: 'medium',
56
- }
57
- setTodos([...todos, todo])
58
- setNewTodo('')
59
- }
60
- }
61
-
62
- const toggleTodo = (id: string) => {
63
- setTodos(todos.map(todo =>
64
- todo.id === id ? { ...todo, completed: !todo.completed } : todo,
65
- ))
66
- }
67
-
68
- const deleteTodo = (id: string) => {
69
- setTodos(todos.filter(todo => todo.id !== id))
70
- }
71
-
72
- const updateTodoPriority = (id: string, priority: Todo['priority']) => {
73
- setTodos(todos.map(todo =>
74
- todo.id === id ? { ...todo, priority } : todo,
75
- ))
76
- }
77
-
78
- const getFilteredTodos = () => {
79
- let filtered = todos
80
-
81
- // Filter by status
82
- switch (filter) {
83
- case 'active':
84
- filtered = filtered.filter(todo => !todo.completed)
85
- break
86
- case 'completed':
87
- filtered = filtered.filter(todo => todo.completed)
88
- break
89
- default:
90
- break
91
- }
92
-
93
- // Sort todos
94
- return filtered.sort((a, b) => {
95
- switch (sortBy) {
96
- case 'priority':
97
- const priorityOrder = { high: 3, medium: 2, low: 1 }
98
- return priorityOrder[b.priority] - priorityOrder[a.priority]
99
- case 'dueDate':
100
- if (!a.dueDate && !b.dueDate)
101
- return 0
102
- if (!a.dueDate)
103
- return 1
104
- if (!b.dueDate)
105
- return -1
106
- return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime()
107
- case 'created':
108
- default:
109
- return Number.parseInt(b.id) - Number.parseInt(a.id)
110
- }
111
- })
112
- }
113
-
114
- // const getPriorityColor = (priority: Todo['priority']) => {
115
- // switch (priority) {
116
- // case 'high': return '#e74c3c'
117
- // case 'medium': return '#f39c12'
118
- // case 'low': return '#27ae60'
119
- // default: return '#95a5a6'
120
- // }
121
- // }
122
-
123
- const getPriorityIcon = (priority: Todo['priority']) => {
124
- switch (priority) {
125
- case 'high': return '🔴'
126
- case 'medium': return '🟡'
127
- case 'low': return '🟢'
128
- default: return '⚪'
129
- }
130
- }
131
-
132
- const completedCount = todos.filter(todo => todo.completed).length
133
- const totalCount = todos.length
134
- const progressPercentage = totalCount > 0 ? (completedCount / totalCount) * 100 : 0
135
-
136
- return (
137
- <div style={{ padding: '20px' }}>
138
- <div style={{ marginBottom: '30px' }}>
139
- <h1 style={{ margin: '0 0 20px 0', color: '#2c3e50' }}>Todo List</h1>
140
-
141
- {/* Progress bar */}
142
- <div style={{
143
- background: 'white',
144
- padding: '20px',
145
- borderRadius: '8px',
146
- boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
147
- marginBottom: '20px',
148
- }}
149
- >
150
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '10px' }}>
151
- <span style={{ fontWeight: 'bold', color: '#2c3e50' }}>Progress</span>
152
- <span style={{ color: '#7f8c8d' }}>
153
- {completedCount}
154
- {' '}
155
- of
156
- {' '}
157
- {totalCount}
158
- {' '}
159
- completed
160
- </span>
161
- </div>
162
- <div style={{
163
- background: '#ecf0f1',
164
- borderRadius: '10px',
165
- height: '10px',
166
- overflow: 'hidden',
167
- }}
168
- >
169
- <div style={{
170
- background: 'linear-gradient(90deg, #27ae60, #2ecc71)',
171
- height: '100%',
172
- width: `${progressPercentage}%`,
173
- transition: 'width 0.3s ease',
174
- }}
175
- />
176
- </div>
177
- </div>
178
-
179
- {/* Add new todo */}
180
- <div style={{
181
- background: 'white',
182
- padding: '20px',
183
- borderRadius: '8px',
184
- boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
185
- marginBottom: '20px',
186
- }}
187
- >
188
- <div style={{ display: 'flex', gap: '10px' }}>
189
- <input
190
- type="text"
191
- placeholder="Add a new todo..."
192
- value={newTodo}
193
- onChange={e => setNewTodo(e.target.value)}
194
- onKeyPress={e => e.key === 'Enter' && addTodo()}
195
- style={{
196
- flex: '1',
197
- padding: '12px 16px',
198
- border: '1px solid #ddd',
199
- borderRadius: '6px',
200
- fontSize: '16px',
201
- }}
202
- />
203
- <button
204
- onClick={addTodo}
205
- style={{
206
- padding: '12px 24px',
207
- background: '#3498db',
208
- color: 'white',
209
- border: 'none',
210
- borderRadius: '6px',
211
- cursor: 'pointer',
212
- fontSize: '16px',
213
- fontWeight: 'bold',
214
- }}
215
- >
216
- Add
217
- </button>
218
- </div>
219
- </div>
220
-
221
- {/* Filters and sorting */}
222
- <div style={{
223
- background: 'white',
224
- padding: '20px',
225
- borderRadius: '8px',
226
- boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
227
- marginBottom: '20px',
228
- }}
229
- >
230
- <div style={{ display: 'flex', gap: '20px', flexWrap: 'wrap', alignItems: 'center' }}>
231
- <div>
232
- <label style={{ marginRight: '10px', fontWeight: 'bold', color: '#2c3e50' }}>Filter:</label>
233
- <select
234
- value={filter}
235
- onChange={e => setFilter(e.target.value as typeof filter)}
236
- style={{
237
- padding: '8px 12px',
238
- border: '1px solid #ddd',
239
- borderRadius: '4px',
240
- }}
241
- >
242
- <option value="all">All</option>
243
- <option value="active">Active</option>
244
- <option value="completed">Completed</option>
245
- </select>
246
- </div>
247
-
248
- <div>
249
- <label style={{ marginRight: '10px', fontWeight: 'bold', color: '#2c3e50' }}>Sort by:</label>
250
- <select
251
- value={sortBy}
252
- onChange={e => setSortBy(e.target.value as typeof sortBy)}
253
- style={{
254
- padding: '8px 12px',
255
- border: '1px solid #ddd',
256
- borderRadius: '4px',
257
- }}
258
- >
259
- <option value="priority">Priority</option>
260
- <option value="dueDate">Due Date</option>
261
- <option value="created">Created</option>
262
- </select>
263
- </div>
264
- </div>
265
- </div>
266
- </div>
267
-
268
- {/* Todo list */}
269
- <div style={{
270
- background: 'white',
271
- borderRadius: '8px',
272
- boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
273
- overflow: 'hidden',
274
- }}
275
- >
276
- {getFilteredTodos().map(todo => (
277
- <div
278
- key={todo.id}
279
- style={{
280
- padding: '20px',
281
- borderBottom: '1px solid #ecf0f1',
282
- display: 'flex',
283
- alignItems: 'center',
284
- gap: '15px',
285
- background: todo.completed ? '#f8f9fa' : 'white',
286
- }}
287
- >
288
- <input
289
- type="checkbox"
290
- checked={todo.completed}
291
- onChange={() => toggleTodo(todo.id)}
292
- style={{
293
- width: '20px',
294
- height: '20px',
295
- cursor: 'pointer',
296
- }}
297
- />
298
-
299
- <div style={{ flex: '1' }}>
300
- <div style={{
301
- display: 'flex',
302
- alignItems: 'center',
303
- gap: '10px',
304
- marginBottom: '5px',
305
- }}
306
- >
307
- <span style={{
308
- fontSize: '18px',
309
- textDecoration: todo.completed ? 'line-through' : 'none',
310
- color: todo.completed ? '#7f8c8d' : '#2c3e50',
311
- }}
312
- >
313
- {todo.text}
314
- </span>
315
-
316
- {todo.category && (
317
- <span style={{
318
- background: '#e9ecef',
319
- color: '#495057',
320
- padding: '2px 8px',
321
- borderRadius: '12px',
322
- fontSize: '12px',
323
- }}
324
- >
325
- {todo.category}
326
- </span>
327
- )}
328
- </div>
329
-
330
- {todo.dueDate && (
331
- <div style={{
332
- fontSize: '14px',
333
- color: '#7f8c8d',
334
- display: 'flex',
335
- alignItems: 'center',
336
- gap: '5px',
337
- }}
338
- >
339
- 📅 Due:
340
- {' '}
341
- {new Date(todo.dueDate).toLocaleDateString()}
342
- </div>
343
- )}
344
- </div>
345
-
346
- <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
347
- <select
348
- value={todo.priority}
349
- onChange={e => updateTodoPriority(todo.id, e.target.value as Todo['priority'])}
350
- style={{
351
- padding: '4px 8px',
352
- border: '1px solid #ddd',
353
- borderRadius: '4px',
354
- fontSize: '12px',
355
- }}
356
- >
357
- <option value="low">Low</option>
358
- <option value="medium">Medium</option>
359
- <option value="high">High</option>
360
- </select>
361
-
362
- <span style={{ fontSize: '16px' }}>
363
- {getPriorityIcon(todo.priority)}
364
- </span>
365
-
366
- <button
367
- onClick={() => deleteTodo(todo.id)}
368
- style={{
369
- background: 'none',
370
- border: 'none',
371
- color: '#e74c3c',
372
- cursor: 'pointer',
373
- fontSize: '18px',
374
- padding: '5px',
375
- }}
376
- >
377
- 🗑️
378
- </button>
379
- </div>
380
- </div>
381
- ))}
382
-
383
- {getFilteredTodos().length === 0 && (
384
- <div style={{
385
- textAlign: 'center',
386
- padding: '40px 20px',
387
- color: '#7f8c8d',
388
- fontStyle: 'italic',
389
- }}
390
- >
391
- {filter === 'all'
392
- ? 'No todos yet. Add one above!'
393
- : filter === 'active'
394
- ? 'No active todos!'
395
- : 'No completed todos!'}
396
- </div>
397
- )}
398
- </div>
399
- </div>
400
- )
401
- }
402
-
403
- // Mount the component
404
- const container = document.getElementById('widget-root')
405
- if (container) {
406
- const root = createRoot(container)
407
- root.render(<TodoList />)
408
- }