customized-calendar 1.0.0

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.
Files changed (27) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +238 -0
  3. package/dist/components/classroom-calendar/AddEventModal.d.ts +14 -0
  4. package/dist/components/classroom-calendar/AddEventModal.d.ts.map +1 -0
  5. package/dist/components/classroom-calendar/AddEventModal.js +131 -0
  6. package/dist/components/classroom-calendar/CustomizedCalendar.d.ts +11 -0
  7. package/dist/components/classroom-calendar/CustomizedCalendar.d.ts.map +1 -0
  8. package/dist/components/classroom-calendar/CustomizedCalendar.js +442 -0
  9. package/dist/components/classroom-calendar/DateEventsList.d.ts +14 -0
  10. package/dist/components/classroom-calendar/DateEventsList.d.ts.map +1 -0
  11. package/dist/components/classroom-calendar/DateEventsList.js +56 -0
  12. package/dist/components/classroom-calendar/EventDetailsModal.d.ts +11 -0
  13. package/dist/components/classroom-calendar/EventDetailsModal.d.ts.map +1 -0
  14. package/dist/components/classroom-calendar/EventDetailsModal.js +37 -0
  15. package/dist/components/classroom-calendar/calendar.types.d.ts +57 -0
  16. package/dist/components/classroom-calendar/calendar.types.d.ts.map +1 -0
  17. package/dist/components/classroom-calendar/calendar.types.js +10 -0
  18. package/dist/components/classroom-calendar/calendar.utils.d.ts +64 -0
  19. package/dist/components/classroom-calendar/calendar.utils.d.ts.map +1 -0
  20. package/dist/components/classroom-calendar/calendar.utils.js +119 -0
  21. package/dist/components/classroom-calendar/index.d.ts +7 -0
  22. package/dist/components/classroom-calendar/index.d.ts.map +1 -0
  23. package/dist/components/classroom-calendar/index.js +6 -0
  24. package/dist/src/index.d.ts +11 -0
  25. package/dist/src/index.d.ts.map +1 -0
  26. package/dist/src/index.js +9 -0
  27. package/package.json +74 -0
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+
package/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # Customized Calendar Component
2
+
3
+ A modern, elegant, and highly customizable calendar component built with React, TypeScript, and FullCalendar. Perfect for any application that needs a beautiful, flexible calendar interface.
4
+
5
+ ## Features
6
+
7
+ ✨ **Modern Design**
8
+ - Clean, elegant UI with gradient accents
9
+ - Responsive layout for all screen sizes
10
+ - Customizable theme colors
11
+ - Smooth animations and transitions
12
+
13
+ 📅 **Multiple Views**
14
+ - Month view
15
+ - Week view
16
+ - Day view
17
+
18
+ 🎯 **Event Management**
19
+ - Color-coded events by type (SESSION, EVENT, EXAM, HOLIDAY)
20
+ - Batch information display
21
+ - Drag & drop support
22
+ - Event resizing
23
+ - Click to view/edit events
24
+
25
+ 📚 **Batch Support**
26
+ - Display batch information for each event
27
+ - Group events by batch
28
+ - Batch-specific filtering
29
+
30
+ 🎨 **Customizable**
31
+ - Theme color support
32
+ - Custom event colors
33
+ - Flexible styling with Tailwind CSS
34
+
35
+ ## Installation
36
+
37
+ ### NPM Package (Recommended)
38
+
39
+ ```bash
40
+ npm install customized-calendar
41
+ # or
42
+ yarn add customized-calendar
43
+ ```
44
+
45
+ **Note:** This component uses Tailwind CSS classes. Make sure Tailwind CSS is configured in your project. See [Styling](#styling) section below for setup instructions.
46
+
47
+ ### Manual Installation
48
+
49
+ If you prefer to copy the component files directly:
50
+
51
+ 1. Copy the `components/classroom-calendar` folder to your project
52
+ 2. Install peer dependencies:
53
+ ```bash
54
+ npm install @fullcalendar/react @fullcalendar/core @fullcalendar/daygrid @fullcalendar/timegrid @fullcalendar/interaction react react-dom
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ ### Using NPM Package
60
+
61
+ ```tsx
62
+ import { CustomizedCalendar, CalendarEvent, EventType } from 'customized-calendar';
63
+
64
+ function MyCalendar() {
65
+ const events: CalendarEvent[] = [
66
+ {
67
+ id: '1',
68
+ title: 'Mathematics Session',
69
+ start: new Date(),
70
+ end: new Date(Date.now() + 90 * 60 * 1000),
71
+ batchId: 'batch-001',
72
+ batchName: 'Batch A - Morning',
73
+ type: EventType.SESSION,
74
+ },
75
+ ];
76
+
77
+ return (
78
+ <CustomizedCalendar
79
+ events={events}
80
+ onDateClick={(date) => console.log('Date:', date)}
81
+ onEventClick={(event) => console.log('Event:', event)}
82
+ themeColor="#3b82f6"
83
+ />
84
+ );
85
+ }
86
+ ```
87
+
88
+ ### Using Copied Component Files
89
+
90
+ ```tsx
91
+ import { CustomizedCalendar, CalendarEvent, EventType } from '@/components/classroom-calendar';
92
+
93
+ function MyCalendar() {
94
+ const events: CalendarEvent[] = [
95
+ {
96
+ id: '1',
97
+ title: 'Mathematics Session',
98
+ start: new Date(),
99
+ end: new Date(Date.now() + 90 * 60 * 1000),
100
+ batchId: 'batch-001',
101
+ batchName: 'Batch A - Morning',
102
+ type: EventType.SESSION,
103
+ },
104
+ ];
105
+
106
+ return (
107
+ <CustomizedCalendar
108
+ events={events}
109
+ onDateClick={(date) => console.log('Date:', date)}
110
+ onEventClick={(event) => console.log('Event:', event)}
111
+ themeColor="#3b82f6"
112
+ />
113
+ );
114
+ }
115
+ ```
116
+
117
+ ## Documentation
118
+
119
+ - **[NPM Publish Guide](./NPM_PUBLISH_GUIDE.md)** - How to publish to NPM
120
+ - **[Quick Integration Guide](./QUICK_INTEGRATION.md)** - 5-minute setup guide
121
+ - **[Reusable Package Guide](./REUSABLE_PACKAGE_GUIDE.md)** - Use in other projects & backend integration
122
+ - **[Quick Start Guide](./QUICK_START.md)** - Get started in 5 minutes
123
+ - **[Integration Guide](./INTEGRATION_GUIDE.md)** - Complete integration documentation
124
+ - **[API Contract](./API_CONTRACT.md)** - Backend API requirements
125
+ - **[Data Structure](./data/README.md)** - Data models and types
126
+
127
+ ## Component Structure
128
+
129
+ ```
130
+ components/classroom-calendar/
131
+ ├── CustomizedCalendar.tsx # Main calendar component
132
+ ├── AddEventModal.tsx # Add event modal
133
+ ├── EventDetailsModal.tsx # Event details modal
134
+ ├── DateEventsList.tsx # Date events list modal
135
+ ├── calendar.types.ts # TypeScript types
136
+ ├── calendar.utils.ts # Utility functions
137
+ └── index.ts # Exports
138
+ ```
139
+
140
+ ## Props
141
+
142
+ ### CustomizedCalendar
143
+
144
+ | Prop | Type | Required | Default | Description |
145
+ |------|------|----------|---------|-------------|
146
+ | `events` | `CalendarEvent[]` | ✅ | - | Array of calendar events |
147
+ | `onDateClick` | `(date: string) => void` | ✅ | - | Callback when date is clicked |
148
+ | `onEventClick` | `(event: CalendarEvent) => void` | ✅ | - | Callback when event is clicked |
149
+ | `height` | `string \| number` | ❌ | `'auto'` | Calendar height |
150
+ | `initialView` | `'dayGridMonth' \| 'timeGridWeek' \| 'timeGridDay'` | ❌ | `'dayGridMonth'` | Initial view |
151
+ | `themeColor` | `string` | ❌ | `'#3b82f6'` | Primary theme color (hex) |
152
+ | `editable` | `boolean` | ❌ | `true` | Enable drag & drop |
153
+ | `selectable` | `boolean` | ❌ | `true` | Enable date selection |
154
+
155
+ ## Event Types
156
+
157
+ - **SESSION**: Regular class sessions (Blue: `#4f46e5`)
158
+ - **EVENT**: Special events, labs, workshops (Green: `#059669`)
159
+ - **EXAM**: Examinations (Red: `#dc2626`)
160
+ - **HOLIDAY**: Holidays (Amber: `#d97706`)
161
+
162
+ ## Examples
163
+
164
+ See `components/classroom-calendar/example-usage.tsx` for complete examples.
165
+
166
+ ## Backend Integration
167
+
168
+ The component can work with any backend that provides calendar events. It's flexible and can be adapted to different API structures.
169
+
170
+ ### Quick Setup
171
+ 1. Copy component files to your project (see [QUICK_INTEGRATION.md](./QUICK_INTEGRATION.md))
172
+ 2. Configure API service (see `services/calendarApi.configurable.ts`)
173
+ 3. Connect to your backend
174
+
175
+ ### Backend Options
176
+ - **REST API** - Standard REST endpoints (see [INTEGRATION_GUIDE.md](./INTEGRATION_GUIDE.md))
177
+ - **GraphQL** - Use GraphQL queries (see [REUSABLE_PACKAGE_GUIDE.md](./REUSABLE_PACKAGE_GUIDE.md))
178
+ - **Firebase/Supabase** - Direct database integration (examples included)
179
+ - **Custom Format** - Adapt to any API structure (see `examples/api-config-examples.ts`)
180
+
181
+ ### Required Endpoints
182
+ - `GET /api/calendar/events` - Get events with date range
183
+ - `POST /api/calendar/events` - Create event
184
+ - `PUT /api/calendar/events/:id` - Update event
185
+ - `DELETE /api/calendar/events/:id` - Delete event
186
+
187
+ See [API_CONTRACT.md](./API_CONTRACT.md) for detailed API documentation and [REUSABLE_PACKAGE_GUIDE.md](./REUSABLE_PACKAGE_GUIDE.md) for backend integration strategies.
188
+
189
+ ## Styling
190
+
191
+ The component uses Tailwind CSS. Ensure Tailwind is configured in your project:
192
+
193
+ ```js
194
+ // tailwind.config.js
195
+ module.exports = {
196
+ content: [
197
+ './components/**/*.{js,ts,jsx,tsx}',
198
+ './node_modules/customized-calendar/dist/**/*.{js,jsx}', // Include package files
199
+ './app/**/*.{js,ts,jsx,tsx}', // Your app files
200
+ ],
201
+ // ... rest of config
202
+ };
203
+ ```
204
+
205
+ **Important:** The component includes inline styles for FullCalendar customization, but Tailwind CSS classes are used for layout and responsive design. Make sure your Tailwind configuration includes the package files in the `content` array.
206
+
207
+ ## Browser Support
208
+
209
+ - Chrome (latest)
210
+ - Firefox (latest)
211
+ - Safari (latest)
212
+ - Edge (latest)
213
+
214
+ ## License
215
+
216
+ MIT
217
+
218
+ ## Using in Other Projects
219
+
220
+ Want to use this calendar in another project? See the comprehensive guide:
221
+
222
+ - **[REUSABLE_PACKAGE_GUIDE.md](./REUSABLE_PACKAGE_GUIDE.md)** - Complete guide for using in other projects
223
+ - Copy component files
224
+ - Configure for different backends
225
+ - API service examples
226
+ - Firebase/GraphQL/Custom backend examples
227
+
228
+ Quick start: Copy `components/classroom-calendar` folder and install dependencies.
229
+
230
+ ## Support
231
+
232
+ For issues or questions:
233
+ 1. Check the [Quick Integration Guide](./QUICK_INTEGRATION.md) for fast setup
234
+ 2. See [Reusable Package Guide](./REUSABLE_PACKAGE_GUIDE.md) for backend integration
235
+ 3. Review [Integration Guide](./INTEGRATION_GUIDE.md) for complete documentation
236
+ 4. Check [API Contract](./API_CONTRACT.md) for backend requirements
237
+ 5. See example implementations in `examples/` folder
238
+
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { Batch, Room, Subject, CalendarEventExtended } from '@/data/mock-calendar-data';
3
+ interface AddEventModalProps {
4
+ isOpen: boolean;
5
+ onClose: () => void;
6
+ onSave: (event: CalendarEventExtended) => void;
7
+ initialDate?: string;
8
+ batches: Batch[];
9
+ rooms: Room[];
10
+ subjects: Subject[];
11
+ }
12
+ declare const AddEventModal: React.FC<AddEventModalProps>;
13
+ export default AddEventModal;
14
+ //# sourceMappingURL=AddEventModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddEventModal.d.ts","sourceRoot":"","sources":["../../../components/classroom-calendar/AddEventModal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAExF,UAAU,kBAAkB;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,KAAK,EAAE,CAAC;IACjB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAyZ/C,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,131 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import { EventType } from './calendar.types';
5
+ const AddEventModal = ({ isOpen, onClose, onSave, initialDate, batches, rooms, subjects, }) => {
6
+ const [formData, setFormData] = useState({
7
+ title: '',
8
+ description: '',
9
+ date: initialDate || new Date().toISOString().split('T')[0],
10
+ startTime: '10:00',
11
+ endTime: '11:30',
12
+ batchId: batches[0]?.id || '',
13
+ type: EventType.SESSION,
14
+ roomId: '',
15
+ subjectId: '',
16
+ color: '',
17
+ isAllDay: false,
18
+ });
19
+ const [errors, setErrors] = useState({});
20
+ if (!isOpen)
21
+ return null;
22
+ const handleChange = (e) => {
23
+ const { name, value, type } = e.target;
24
+ const checked = e.target.checked;
25
+ setFormData((prev) => ({
26
+ ...prev,
27
+ [name]: type === 'checkbox' ? checked : value,
28
+ }));
29
+ // Clear error when user starts typing
30
+ if (errors[name]) {
31
+ setErrors((prev) => {
32
+ const newErrors = { ...prev };
33
+ delete newErrors[name];
34
+ return newErrors;
35
+ });
36
+ }
37
+ };
38
+ const validateForm = () => {
39
+ const newErrors = {};
40
+ if (!formData.title.trim()) {
41
+ newErrors.title = 'Title is required';
42
+ }
43
+ if (!formData.batchId) {
44
+ newErrors.batchId = 'Batch is required';
45
+ }
46
+ if (!formData.isAllDay) {
47
+ if (!formData.startTime) {
48
+ newErrors.startTime = 'Start time is required';
49
+ }
50
+ if (!formData.endTime) {
51
+ newErrors.endTime = 'End time is required';
52
+ }
53
+ // Validate end time is after start time
54
+ if (formData.startTime && formData.endTime) {
55
+ const [startHour, startMin] = formData.startTime.split(':').map(Number);
56
+ const [endHour, endMin] = formData.endTime.split(':').map(Number);
57
+ const startMinutes = startHour * 60 + startMin;
58
+ const endMinutes = endHour * 60 + endMin;
59
+ if (endMinutes <= startMinutes) {
60
+ newErrors.endTime = 'End time must be after start time';
61
+ }
62
+ }
63
+ }
64
+ setErrors(newErrors);
65
+ return Object.keys(newErrors).length === 0;
66
+ };
67
+ const handleSubmit = (e) => {
68
+ e.preventDefault();
69
+ if (!validateForm()) {
70
+ return;
71
+ }
72
+ const selectedBatch = batches.find((b) => b.id === formData.batchId);
73
+ const selectedRoom = formData.roomId ? rooms.find((r) => r.id === formData.roomId) : null;
74
+ const selectedSubject = formData.subjectId ? subjects.find((s) => s.id === formData.subjectId) : null;
75
+ // Create event dates
76
+ let start;
77
+ let end;
78
+ if (formData.isAllDay) {
79
+ start = formData.date;
80
+ end = formData.date;
81
+ }
82
+ else {
83
+ start = `${formData.date}T${formData.startTime}:00`;
84
+ end = `${formData.date}T${formData.endTime}:00`;
85
+ }
86
+ const newEvent = {
87
+ id: `event-${Date.now()}`,
88
+ title: formData.title,
89
+ description: formData.description || undefined,
90
+ start,
91
+ end,
92
+ batchId: formData.batchId,
93
+ batchName: selectedBatch?.name || '',
94
+ type: formData.type,
95
+ color: formData.color || undefined,
96
+ room: selectedRoom || null,
97
+ instructor: selectedBatch?.instructor || null,
98
+ subject: selectedSubject || null,
99
+ status: 'SCHEDULED',
100
+ createdAt: new Date().toISOString(),
101
+ updatedAt: new Date().toISOString(),
102
+ };
103
+ onSave(newEvent);
104
+ // Reset form
105
+ setFormData({
106
+ title: '',
107
+ description: '',
108
+ date: initialDate || new Date().toISOString().split('T')[0],
109
+ startTime: '10:00',
110
+ endTime: '11:30',
111
+ batchId: batches[0]?.id || '',
112
+ type: EventType.SESSION,
113
+ roomId: '',
114
+ subjectId: '',
115
+ color: '',
116
+ isAllDay: false,
117
+ });
118
+ onClose();
119
+ };
120
+ const getEventTypeColor = (type) => {
121
+ const colorMap = {
122
+ [EventType.SESSION]: '#4f46e5',
123
+ [EventType.EVENT]: '#059669',
124
+ [EventType.EXAM]: '#dc2626',
125
+ [EventType.HOLIDAY]: '#d97706',
126
+ };
127
+ return colorMap[type] || '#6366f1';
128
+ };
129
+ return (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 backdrop-blur-sm", children: _jsxs("div", { className: "bg-white rounded-2xl shadow-2xl max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto", children: [_jsx("div", { className: "sticky top-0 bg-gradient-to-r from-blue-600 to-purple-600 text-white p-6 rounded-t-2xl", children: _jsxs("div", { className: "flex justify-between items-center", children: [_jsx("h2", { className: "text-2xl font-bold", children: "Add New Event" }), _jsx("button", { onClick: onClose, className: "text-white hover:text-gray-200 transition-colors p-2 hover:bg-white/20 rounded-lg", children: _jsx("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }) }), _jsxs("form", { onSubmit: handleSubmit, className: "p-6 space-y-6", children: [_jsxs("div", { children: [_jsxs("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: ["Event Title ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx("input", { type: "text", name: "title", value: formData.title, onChange: handleChange, className: `w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent ${errors.title ? 'border-red-500' : 'border-gray-300'}`, placeholder: "e.g., Mathematics Session" }), errors.title && _jsx("p", { className: "text-red-500 text-sm mt-1", children: errors.title })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: "Description" }), _jsx("textarea", { name: "description", value: formData.description, onChange: handleChange, rows: 3, className: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent", placeholder: "Event description..." })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsxs("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: ["Date ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx("input", { type: "date", name: "date", value: formData.date, onChange: handleChange, className: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" })] }), _jsx("div", { className: "flex items-end", children: _jsxs("label", { className: "flex items-center space-x-2 cursor-pointer", children: [_jsx("input", { type: "checkbox", name: "isAllDay", checked: formData.isAllDay, onChange: handleChange, className: "w-5 h-5 text-blue-600 rounded focus:ring-blue-500" }), _jsx("span", { className: "text-sm font-semibold text-gray-700", children: "All Day Event" })] }) })] }), !formData.isAllDay && (_jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsxs("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: ["Start Time ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx("input", { type: "time", name: "startTime", value: formData.startTime, onChange: handleChange, className: `w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent ${errors.startTime ? 'border-red-500' : 'border-gray-300'}` }), errors.startTime && _jsx("p", { className: "text-red-500 text-sm mt-1", children: errors.startTime })] }), _jsxs("div", { children: [_jsxs("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: ["End Time ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx("input", { type: "time", name: "endTime", value: formData.endTime, onChange: handleChange, className: `w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent ${errors.endTime ? 'border-red-500' : 'border-gray-300'}` }), errors.endTime && _jsx("p", { className: "text-red-500 text-sm mt-1", children: errors.endTime })] })] })), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsxs("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: ["Batch ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsxs("select", { name: "batchId", value: formData.batchId, onChange: handleChange, className: `w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent ${errors.batchId ? 'border-red-500' : 'border-gray-300'}`, children: [_jsx("option", { value: "", children: "Select a batch" }), batches.map((batch) => (_jsxs("option", { value: batch.id, children: [batch.name, " (", batch.code, ")"] }, batch.id)))] }), errors.batchId && _jsx("p", { className: "text-red-500 text-sm mt-1", children: errors.batchId })] }), _jsxs("div", { children: [_jsxs("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: ["Event Type ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx("select", { name: "type", value: formData.type, onChange: handleChange, className: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent", children: Object.values(EventType).map((type) => (_jsx("option", { value: type, children: type }, type))) })] })] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: "Room" }), _jsxs("select", { name: "roomId", value: formData.roomId, onChange: handleChange, className: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent", children: [_jsx("option", { value: "", children: "Select a room (optional)" }), rooms.map((room) => (_jsxs("option", { value: room.id, children: [room.name, " - ", room.building, " (Floor ", room.floor, ")"] }, room.id)))] })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: "Subject" }), _jsxs("select", { name: "subjectId", value: formData.subjectId, onChange: handleChange, className: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent", children: [_jsx("option", { value: "", children: "Select a subject (optional)" }), subjects.map((subject) => (_jsxs("option", { value: subject.id, children: [subject.name, " (", subject.code, ")"] }, subject.id)))] })] })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-semibold text-gray-700 mb-2", children: "Custom Color (optional)" }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx("input", { type: "color", name: "color", value: formData.color || getEventTypeColor(formData.type), onChange: handleChange, className: "w-16 h-10 border border-gray-300 rounded-lg cursor-pointer" }), _jsx("input", { type: "text", name: "color", value: formData.color, onChange: handleChange, placeholder: "#4f46e5", className: "flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" }), _jsx("button", { type: "button", onClick: () => setFormData((prev) => ({ ...prev, color: '' })), className: "px-4 py-2 text-sm text-gray-600 hover:text-gray-800 border border-gray-300 rounded-lg hover:bg-gray-50", children: "Use Default" })] }), _jsxs("p", { className: "text-xs text-gray-500 mt-1", children: ["Default: ", getEventTypeColor(formData.type), " for ", formData.type] })] }), _jsxs("div", { className: "flex justify-end gap-3 pt-4 border-t", children: [_jsx("button", { type: "button", onClick: onClose, className: "px-6 py-2 bg-gray-200 text-gray-700 rounded-lg font-semibold hover:bg-gray-300 transition-colors", children: "Cancel" }), _jsx("button", { type: "submit", className: "px-6 py-2 bg-gradient-to-r from-blue-600 to-purple-600 text-white rounded-lg font-semibold hover:from-blue-700 hover:to-purple-700 transition-all shadow-lg", children: "Add Event" })] })] })] }) }));
130
+ };
131
+ export default AddEventModal;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { CustomizedCalendarProps } from './calendar.types';
3
+ /**
4
+ * CustomizedCalendar Component
5
+ *
6
+ * A modern, reusable calendar component with customizable theme
7
+ * and support for multiple views, event management, and advanced interactions.
8
+ */
9
+ declare const CustomizedCalendar: React.FC<CustomizedCalendarProps>;
10
+ export default CustomizedCalendar;
11
+ //# sourceMappingURL=CustomizedCalendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomizedCalendar.d.ts","sourceRoot":"","sources":["../../../components/classroom-calendar/CustomizedCalendar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAK3D,OAAO,EACL,uBAAuB,EAExB,MAAM,kBAAkB,CAAC;AAY1B;;;;;GAKG;AACH,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAshBzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}