@@ -16,8 +16,14 @@ export function CalendarSelector() {
16
16
queryFn : async ( ) => {
17
17
const calendars = await dbCommands . listCalendars ( userId ) ;
18
18
const grouped = calendars . reduce ( ( acc , calendar ) => {
19
- acc [ calendar . source || "Other" ] = acc [ calendar . source || "Other" ] || [ ] ;
20
- acc [ calendar . source || "Other" ] . push ( calendar ) ;
19
+ let source = calendar . source || "Other" ;
20
+
21
+ if ( ! source . includes ( "@" ) ) {
22
+ source = "Other" ;
23
+ }
24
+
25
+ acc [ source ] = acc [ source ] || [ ] ;
26
+ acc [ source ] . push ( calendar ) ;
21
27
return acc ;
22
28
} , { } as Record < string , Calendar [ ] > ) ;
23
29
@@ -101,29 +107,93 @@ export function CalendarSelector() {
101
107
</ div >
102
108
)
103
109
: (
104
- Object . entries ( calendarsQuery . data ?. grouped ?? { } ) . map ( ( [ source , sourceCalendars ] ) => (
110
+ Object . entries ( calendarsQuery . data ?. grouped ?? { } ) . sort ( ( [ sourceA ] , [ sourceB ] ) => {
111
+ const isWorkEmail = ( email : string ) => {
112
+ if ( ! email . includes ( "@" ) ) {
113
+ return false ;
114
+ }
115
+
116
+ const domain = email . split ( "@" ) [ 1 ] ?. toLowerCase ( ) ;
117
+
118
+ const personalDomains = [
119
+ "gmail.com" ,
120
+ "yahoo.com" ,
121
+ "hotmail.com" ,
122
+ "outlook.com" ,
123
+ "icloud.com" ,
124
+ "aol.com" ,
125
+ "protonmail.com" ,
126
+ "mail.com" ,
127
+ ] ;
128
+
129
+ return domain && ! personalDomains . includes ( domain ) ;
130
+ } ;
131
+
132
+ const isWorkEmailA = isWorkEmail ( sourceA ) ;
133
+ const isWorkEmailB = isWorkEmail ( sourceB ) ;
134
+
135
+ if ( isWorkEmailA && ! isWorkEmailB ) {
136
+ return - 1 ;
137
+ }
138
+ if ( ! isWorkEmailA && isWorkEmailB ) {
139
+ return 1 ;
140
+ }
141
+
142
+ if ( sourceA . includes ( "@" ) && ! sourceB . includes ( "@" ) ) {
143
+ return - 1 ;
144
+ }
145
+ if ( ! sourceA . includes ( "@" ) && sourceB . includes ( "@" ) ) {
146
+ return 1 ;
147
+ }
148
+
149
+ if ( sourceA === "Other" && sourceB !== "Other" ) {
150
+ return 1 ;
151
+ }
152
+ if ( sourceA !== "Other" && sourceB === "Other" ) {
153
+ return - 1 ;
154
+ }
155
+
156
+ return sourceA . localeCompare ( sourceB ) ;
157
+ } ) . map ( ( [ source , sourceCalendars ] ) => (
105
158
< div key = { source } className = "mb-5" >
106
159
< div className = "text-sm font-semibold text-gray-800 mb-2" > { source } </ div >
107
160
< div className = "pl-2 space-y-2.5" >
108
- { sourceCalendars . map ( ( calendar ) => (
109
- < div
110
- key = { calendar . id }
111
- className = "flex items-center space-x-3 py-1 px-2 rounded-md hover:bg-gray-50 transition-colors"
112
- >
113
- < Checkbox
114
- id = { `calendar-${ calendar . id } ` }
115
- checked = { calendar . selected }
116
- onCheckedChange = { ( ) => toggleCalendarSelectedMutation . mutate ( calendar ) }
117
- className = "h-4 w-4"
118
- />
119
- < label
120
- htmlFor = { `calendar-${ calendar . id } ` }
121
- className = "text-sm font-medium cursor-pointer text-gray-700 flex-1"
161
+ { sourceCalendars
162
+ . sort ( ( a , b ) => {
163
+ // Check if calendar names contain email addresses
164
+ const aHasEmail = a . name . includes ( "@" ) ;
165
+ const bHasEmail = b . name . includes ( "@" ) ;
166
+
167
+ // Email-based calendars first
168
+ if ( aHasEmail && ! bHasEmail ) {
169
+ return - 1 ;
170
+ }
171
+ if ( ! aHasEmail && bHasEmail ) {
172
+ return 1 ;
173
+ }
174
+
175
+ // Then alphabetical order
176
+ return a . name . localeCompare ( b . name ) ;
177
+ } )
178
+ . map ( ( calendar ) => (
179
+ < div
180
+ key = { calendar . id }
181
+ className = "flex items-center space-x-3 py-1 px-2 rounded-md hover:bg-gray-50 transition-colors"
122
182
>
123
- { calendar . name }
124
- </ label >
125
- </ div >
126
- ) ) }
183
+ < Checkbox
184
+ id = { `calendar-${ calendar . id } ` }
185
+ checked = { calendar . selected }
186
+ onCheckedChange = { ( ) => toggleCalendarSelectedMutation . mutate ( calendar ) }
187
+ className = "h-4 w-4"
188
+ />
189
+ < label
190
+ htmlFor = { `calendar-${ calendar . id } ` }
191
+ className = "text-sm font-medium cursor-pointer text-gray-700 flex-1"
192
+ >
193
+ { calendar . name }
194
+ </ label >
195
+ </ div >
196
+ ) ) }
127
197
</ div >
128
198
</ div >
129
199
) )
0 commit comments