@propriety/court-calendar 0.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 (53) hide show
  1. package/.editorconfig +26 -0
  2. package/README.md +0 -0
  3. package/biome.json +302 -0
  4. package/dev/App.tsx +51 -0
  5. package/dev/main.tsx +10 -0
  6. package/index.html +12 -0
  7. package/package.json +54 -0
  8. package/public/vite.svg +1 -0
  9. package/src/_components/CCalendar.css +463 -0
  10. package/src/_components/CCalendar.tsx +726 -0
  11. package/src/_components/List/CalendarList.tsx +288 -0
  12. package/src/_components/Modal/CaseDetails/CaseDetails.tsx +414 -0
  13. package/src/_components/Modal/CaseDetails/EvidenceRow.tsx +83 -0
  14. package/src/_components/Modal/CaseDetails/EvidenceSection.tsx +94 -0
  15. package/src/_components/Modal/CreateEdit/CreateEditCase.tsx +241 -0
  16. package/src/_components/Modal/CreateEdit/DateSelector.tsx +42 -0
  17. package/src/_components/Modal/CreateEdit/EditUserFieldDropdown.tsx +54 -0
  18. package/src/_components/Modal/CreateEdit/EnumDropdown.tsx +54 -0
  19. package/src/_components/Modal/CreateEdit/HearingOfficerDropdown.tsx +48 -0
  20. package/src/_components/Modal/CreateEdit/TextFieldList.tsx +186 -0
  21. package/src/_components/Modal/CreateEdit/ToggleableTextField.tsx +91 -0
  22. package/src/_components/Modal/Modal.css +15 -0
  23. package/src/_components/Modal/Modal.tsx +325 -0
  24. package/src/_components/Modal/ModalActions.tsx +99 -0
  25. package/src/_components/Modal/View/CaseToolbar.tsx +81 -0
  26. package/src/_components/Modal/View/CaseViewer.tsx +237 -0
  27. package/src/_components/Modal/View/DateDetails.tsx +138 -0
  28. package/src/_components/Modal/View/InfoBox.tsx +22 -0
  29. package/src/_components/Modal/View/InfoBoxBtn.css +39 -0
  30. package/src/_components/Modal/View/InfoBoxBtn.tsx +29 -0
  31. package/src/_components/Modal/View/NoticeFileLink.tsx +44 -0
  32. package/src/_components/Shared/FirstSecondChairIcons.tsx +247 -0
  33. package/src/_components/Shared/FormRow.tsx +37 -0
  34. package/src/_components/Shared/MuniDropdown.tsx +94 -0
  35. package/src/_components/Shared/SearchBar.tsx +87 -0
  36. package/src/_components/Toolbar/CaseFilter.tsx +77 -0
  37. package/src/_components/Toolbar/DateTypeFilter.tsx +63 -0
  38. package/src/_components/Toolbar/HearingTypeFilter.tsx +63 -0
  39. package/src/_components/Toolbar/Toolbar.tsx +159 -0
  40. package/src/_components/Toolbar/UserFilter.tsx +105 -0
  41. package/src/_components/Toolbar/ViewFilter.tsx +48 -0
  42. package/src/helpers/cache.ts +89 -0
  43. package/src/helpers/cases.ts +79 -0
  44. package/src/helpers/courtDates.ts +139 -0
  45. package/src/helpers/formatter.ts +16 -0
  46. package/src/helpers/munis.ts +44 -0
  47. package/src/helpers/people.ts +46 -0
  48. package/src/index.ts +2 -0
  49. package/src/types.ts +129 -0
  50. package/tsconfig.app.json +32 -0
  51. package/tsconfig.json +4 -0
  52. package/tsconfig.node.json +30 -0
  53. package/vite.config.ts +27 -0
@@ -0,0 +1,288 @@
1
+ import { getCountyName, getTownshipName } from '@/helpers/munis';
2
+ import { HearingType, Lifecycle, type Case, type CourtDate } from '@/types';
3
+ import { DataGrid, type GridColDef } from '@mui/x-data-grid';
4
+ import FirstSecondChairIcons from '../Shared/FirstSecondChairIcons';
5
+ import { isCaseSettled } from '@/helpers/cases';
6
+ import { isVillageDate } from '@/helpers/courtDates';
7
+
8
+ export default function CalendarList({
9
+ filteredDates,
10
+ setSelectedDate,
11
+ currentDate,
12
+ onUpdateChair,
13
+ allCases,
14
+ }: {
15
+ filteredDates: CourtDate[];
16
+ setSelectedDate: (date: CourtDate) => void;
17
+ currentDate: Date;
18
+ onUpdateChair?: (courtDateId: number, position: 'first' | 'second', userId: number | null) => void;
19
+ allCases: Record<string, Case[]>;
20
+ }) {
21
+ const countyColors: Record<string, string> = {
22
+ Blank: '#c4c4c4',
23
+ Suffolk: '#faa1f1',
24
+ Sullivan: '#00c875',
25
+ Westchester: '#df2f4a',
26
+ Ulster: '#225091',
27
+ Columbia: '#9d50dd',
28
+ Rockland: '#037f4c',
29
+ Putnam: '#579bfc',
30
+ Nassau: '#cab641',
31
+ Greene: '#9cd326',
32
+ Dutchess: '#ffcb00',
33
+ Orange: '#ff6d3b',
34
+ Delaware: '#bb3354',
35
+ };
36
+
37
+ const typeColors: Record<string, string> = {
38
+ 'Court Dates': '#216edf',
39
+ Negotiations: '#33d391',
40
+ };
41
+
42
+ const statusColors: Record<string, string> = {
43
+ Blank: '#c4c4c4', // default
44
+ Reviewing: '#fdab3d', // dateCompleted not set
45
+ Scheduled: '#216edf', // Lifecycle.SCHEDULED or Lifecycle.ASSIGNED
46
+ 'NYSCEF Uploaded': '#037f4c', // Status.UPLOADED
47
+ Adjourned: '#faa1f1', // isAdjourned true
48
+ 'Settled/Decision': '#df2f4a', // isCaseSettled true
49
+ };
50
+
51
+ function determineStatus(date: CourtDate): string {
52
+ let allSettled = true;
53
+ let allReviewed = true;
54
+ for (const caseItem of allCases[date.CourtDateID] || []) {
55
+ if (allSettled && !isCaseSettled(caseItem, isVillageDate(date.MuniCode))) {
56
+ allSettled = false;
57
+ }
58
+ if (allReviewed && caseItem.DateCompleted === null) {
59
+ allReviewed = false;
60
+ }
61
+ }
62
+
63
+ if (!allReviewed) return 'Reviewing';
64
+ if (allSettled) return 'Settled/Decision';
65
+ if (date.Lifecycle === Lifecycle.UPLOADED) return 'NYSCEF Uploaded';
66
+ if (date.Lifecycle === Lifecycle.ADJOURNED) return 'Adjourned';
67
+ if (date.Lifecycle === Lifecycle.SCHEDULED || date.Lifecycle === Lifecycle.ASSIGNED) return 'Scheduled';
68
+
69
+ return 'Blank';
70
+ }
71
+
72
+ function determineLocation(date: CourtDate): string {
73
+ if (date.Type === HearingType.IN_PERSON) return 'In Person';
74
+ if (date.Type === HearingType.UNKNOWN) return 'Unknown';
75
+ return 'Virtual';
76
+ }
77
+
78
+ const locationColors: Record<string, string> = {
79
+ Virtual: 'var(--fc-event-virtual-color)',
80
+ 'In Person': 'var(--fc-event-inperson-color)',
81
+ Unknown: 'var(--fc-event-unknown-color)',
82
+ };
83
+
84
+ const columns: GridColDef[] = [
85
+ {
86
+ field: 'township',
87
+ headerName: 'Municipality',
88
+ width: 150,
89
+ disableColumnMenu: true,
90
+ },
91
+ {
92
+ field: 'county',
93
+ headerName: 'County',
94
+ width: 125,
95
+ disableColumnMenu: true,
96
+ renderCell: (params) => {
97
+ const county = params.value as string;
98
+ const color = countyColors[county] || '#c4c4c4';
99
+ return (
100
+ <span
101
+ style={{
102
+ backgroundColor: color,
103
+ color: '#fff',
104
+ padding: '4px 8px',
105
+ borderRadius: '4px',
106
+ fontWeight: 'bold',
107
+ border: `1px solid`,
108
+ }}
109
+ >
110
+ {county}
111
+ </span>
112
+ );
113
+ },
114
+ },
115
+ {
116
+ field: 'type',
117
+ headerName: 'Type',
118
+ width: 125,
119
+ disableColumnMenu: true,
120
+ renderCell: (params) => {
121
+ const type = params.value as string;
122
+ const color = typeColors[type] || '#c4c4c4';
123
+ return (
124
+ <span
125
+ style={{
126
+ backgroundColor: color,
127
+ color: '#fff',
128
+ padding: '4px 8px',
129
+ borderRadius: '4px',
130
+ fontWeight: 'bold',
131
+ border: `1px solid`,
132
+ }}
133
+ >
134
+ {type}
135
+ </span>
136
+ );
137
+ },
138
+ },
139
+ {
140
+ field: 'district',
141
+ headerName: 'District',
142
+ width: 75,
143
+ disableColumnMenu: true,
144
+ },
145
+ {
146
+ field: 'numCases',
147
+ headerName: '# Cases',
148
+ width: 75,
149
+ disableColumnMenu: true,
150
+ },
151
+ {
152
+ field: 'courtDate',
153
+ headerName: 'Court Date',
154
+ width: 125,
155
+ disableColumnMenu: true,
156
+ valueFormatter: (params: Date) => {
157
+ const date = new Date(params);
158
+ return date.toLocaleDateString();
159
+ },
160
+ },
161
+ {
162
+ field: 'status',
163
+ headerName: 'Status',
164
+ width: 150,
165
+ disableColumnMenu: true,
166
+ renderCell: (params) => {
167
+ const status = params.value as string;
168
+ const color = statusColors[status] || '#c4c4c4';
169
+ return (
170
+ <span
171
+ style={{
172
+ backgroundColor: color,
173
+ color: '#fff',
174
+ padding: '4px 8px',
175
+ borderRadius: '4px',
176
+ fontWeight: 'bold',
177
+ border: `1px solid`,
178
+ }}
179
+ >
180
+ {status}
181
+ </span>
182
+ );
183
+ },
184
+ },
185
+ {
186
+ field: 'assigned',
187
+ headerName: 'Assigned',
188
+ width: 125,
189
+ disableColumnMenu: true,
190
+ renderCell: (params) => {
191
+ const assigned = params.value as {
192
+ user1ID: number | null;
193
+ user2ID: number | null;
194
+ courtDateId: number;
195
+ };
196
+ return (
197
+ <FirstSecondChairIcons
198
+ user1ID={assigned.user1ID}
199
+ user2ID={assigned.user2ID}
200
+ onUpdateChair={
201
+ onUpdateChair
202
+ ? (position, userId) => onUpdateChair(assigned.courtDateId, position, userId)
203
+ : undefined
204
+ }
205
+ />
206
+ );
207
+ },
208
+ },
209
+ {
210
+ field: 'uploadDeadline',
211
+ headerName: 'Upload Deadline',
212
+ width: 125,
213
+ disableColumnMenu: true,
214
+ valueFormatter: (params: Date) => {
215
+ const date = new Date(params);
216
+ return date.toLocaleDateString();
217
+ },
218
+ },
219
+ {
220
+ field: 'location',
221
+ headerName: 'Location',
222
+ width: 125,
223
+ disableColumnMenu: true,
224
+ renderCell: (params) => {
225
+ const location = params.value as string;
226
+ const color = locationColors[location] || '#c4c4c4';
227
+ return (
228
+ <span
229
+ style={{
230
+ backgroundColor: color,
231
+ color: '#fff',
232
+ padding: '4px 8px',
233
+ borderRadius: '4px',
234
+ fontWeight: 'bold',
235
+ border: `1px solid`,
236
+ }}
237
+ >
238
+ {location}
239
+ </span>
240
+ );
241
+ },
242
+ },
243
+ ];
244
+
245
+ const rows = filteredDates
246
+ .filter((date) => {
247
+ if (!date.CourtDate) return false;
248
+ const courtDate = new Date(date.CourtDate);
249
+ return (
250
+ courtDate.getMonth() === currentDate.getMonth() && courtDate.getFullYear() === currentDate.getFullYear()
251
+ );
252
+ })
253
+ .map((date) => ({
254
+ id: date.CourtDateID,
255
+ township: getTownshipName(date.MuniCode),
256
+ county: getCountyName(date.MuniCode),
257
+ type: 'Court Dates', // TODO support negotiations
258
+ district: date.MuniCode,
259
+ numCases: date.CourtCases,
260
+ courtDate: date.CourtDate,
261
+ status: determineStatus(date),
262
+ assigned: { user1ID: date.FirstChair, user2ID: date.SecondChair, courtDateId: date.CourtDateID },
263
+ uploadDeadline: date.UploadDeadline,
264
+ location: determineLocation(date),
265
+ }));
266
+
267
+ return (
268
+ <div style={{ height: 600, width: '100%' }}>
269
+ <DataGrid
270
+ rows={rows}
271
+ columns={columns}
272
+ className='themed'
273
+ initialState={{
274
+ sorting: {
275
+ sortModel: [{ field: 'courtDate', sort: 'asc' }],
276
+ },
277
+ }}
278
+ onRowClick={(params) => {
279
+ const selected = filteredDates.find((date) => date.CourtDateID === params.id);
280
+ if (selected) {
281
+ setSelectedDate(selected);
282
+ }
283
+ }}
284
+ getRowClassName={() => 'ccalendar-list-row'}
285
+ />
286
+ </div>
287
+ );
288
+ }