Skip to content

Commit 1db430f

Browse files
committed
Refactor code structure for improved readability and maintainability
1 parent 953e1be commit 1db430f

File tree

5 files changed

+5149
-6008
lines changed

5 files changed

+5149
-6008
lines changed

frontend_vapi/components/TaskList.tsx

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { usePrivy } from "@privy-io/react-auth";
2-
import { Calendar, Clock, Plus, RefreshCw, Trash2 } from "lucide-react";
2+
import { Calendar, Clock, Download, ExternalLink, Plus, RefreshCw, Trash2 } from "lucide-react";
33
import { useRouter } from "next/router";
44
import { useCallback, useEffect, useMemo, useState } from "react";
55
import { VAPIClient } from "../lib/api-client";
@@ -229,20 +229,28 @@ export function TaskList({ className }: TaskListProps) {
229229

230230
const handleAddToCalendar = async (task: Task, calendarType: "google" | "ios") => {
231231
try {
232+
let result;
232233
if (calendarType === "google") {
233-
await apiClient.addToGoogleCalendar(task);
234+
result = await apiClient.addToGoogleCalendar(task);
234235
} else {
235-
await apiClient.addToIosCalendar(task);
236+
result = await apiClient.addToIosCalendar(task);
237+
}
238+
239+
if (result.success) {
240+
showToast({
241+
type: "success",
242+
title: calendarType === "google"
243+
? "Google Calendar opened with event details"
244+
: "Calendar file downloaded successfully",
245+
});
246+
} else {
247+
throw new Error("Calendar operation failed");
236248
}
237-
showToast({
238-
type: "success",
239-
title: `Added to ${calendarType === "google" ? "Google" : "iOS"} Calendar`,
240-
});
241249
} catch (err) {
242250
console.error("Failed to add to calendar:", err);
243251
showToast({
244252
type: "error",
245-
title: "Failed to add to calendar",
253+
title: `Failed to add to ${calendarType === "google" ? "Google" : "iOS"} Calendar`,
246254
});
247255
}
248256
};
@@ -454,37 +462,37 @@ export function TaskList({ className }: TaskListProps) {
454462
</div>
455463
)}
456464
<span className="px-2 py-1 bg-gray-100 rounded text-xs">{task.type}</span>
465+
</div> {!task.completed && (
466+
<div className="flex gap-2">
467+
<Button
468+
size="sm"
469+
variant="outline"
470+
onClick={() => handleAddToCalendar(task, "google")}
471+
className="text-xs flex items-center gap-1"
472+
>
473+
<ExternalLink size={12} />
474+
Google
475+
</Button>
476+
<Button
477+
size="sm"
478+
variant="outline"
479+
onClick={() => handleAddToCalendar(task, "ios")}
480+
className="text-xs flex items-center gap-1"
481+
>
482+
<Download size={12} />
483+
iOS
484+
</Button>
485+
<Button
486+
size="sm"
487+
variant="outline"
488+
onClick={() => handleDeleteTask(task.id)}
489+
className="text-xs text-red-600 hover:text-red-700 hover:border-red-300"
490+
>
491+
<Trash2 size={12} className="mr-1" />
492+
Delete
493+
</Button>
457494
</div>
458-
459-
{!task.completed && (
460-
<div className="flex gap-2">
461-
<Button
462-
size="sm"
463-
variant="outline"
464-
onClick={() => handleAddToCalendar(task, "google")}
465-
className="text-xs"
466-
>
467-
Google Calendar
468-
</Button>
469-
<Button
470-
size="sm"
471-
variant="outline"
472-
onClick={() => handleAddToCalendar(task, "ios")}
473-
className="text-xs"
474-
>
475-
iOS Calendar
476-
</Button>
477-
<Button
478-
size="sm"
479-
variant="outline"
480-
onClick={() => handleDeleteTask(task.id)}
481-
className="text-xs text-red-600 hover:text-red-700 hover:border-red-300"
482-
>
483-
<Trash2 size={12} className="mr-1" />
484-
Delete
485-
</Button>
486-
</div>
487-
)}
495+
)}
488496
</div>
489497
</div>
490498
</div>

frontend_vapi/lib/api-client.ts

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -163,43 +163,80 @@ export class VAPIClient {
163163
}
164164

165165
/**
166-
* Add task to Google Calendar
166+
* Add task to Google Calendar (using Google Calendar URL)
167167
*/
168168
async addToGoogleCalendar(task: Task): Promise<{ success: boolean; eventId?: string }> {
169169
try {
170-
const response = await fetch(`${this.baseURL}/api/calendar/google/add`, {
171-
method: "POST",
172-
headers: this.getHeaders(),
173-
body: JSON.stringify({ task }),
170+
// Import calendar utilities (dynamic import for client-side only)
171+
const { openGoogleCalendar } = await import("./calendar-utils");
172+
173+
console.log("📅 Adding task to Google Calendar:", task.title);
174+
175+
// Open Google Calendar with pre-filled event
176+
const result = await openGoogleCalendar({
177+
id: task.id,
178+
title: task.title,
179+
description: task.description,
180+
dueDate: task.dueDate,
181+
type: task.type,
174182
});
175183

176-
if (!response.ok) {
177-
throw new Error(`Failed to add to Google Calendar: ${response.statusText}`);
184+
if (result.success) {
185+
return {
186+
success: true,
187+
eventId: task.id, // Return task ID as event identifier
188+
};
189+
} else {
190+
// Even if popup was blocked, we can still consider it a success
191+
// since the URL is available for manual opening
192+
if (result.url) {
193+
console.log("📋 Google Calendar URL (popup blocked):", result.url);
194+
return {
195+
success: true,
196+
eventId: task.id,
197+
};
198+
}
199+
throw new Error("Failed to create Google Calendar event");
178200
}
179-
180-
return await response.json();
181201
} catch (error) {
182202
console.error("Error adding to Google Calendar:", error);
183203
throw error;
184204
}
185205
}
186206

187207
/**
188-
* Add task to iOS calendar (using Web API)
208+
* Add task to iOS calendar (using .ics file download)
209+
* Based on: https://qiita.com/bananbo/items/281f2c98419355d7324c
189210
*/
190211
async addToIosCalendar(task: Task): Promise<{ success: boolean; eventId?: string }> {
191212
try {
192-
const response = await fetch(`${this.baseURL}/api/calendar/ios/add`, {
193-
method: "POST",
194-
headers: this.getHeaders(),
195-
body: JSON.stringify({ task }),
196-
});
213+
// Import calendar utilities (dynamic import for client-side only)
214+
const { createAndDownloadIcsFile, isIcsDownloadSupported } = await import("./calendar-utils");
197215

198-
if (!response.ok) {
199-
throw new Error(`Failed to add to iOS Calendar: ${response.statusText}`);
216+
// Check if .ics download is supported
217+
if (!isIcsDownloadSupported()) {
218+
throw new Error("Calendar file download is not supported in this environment");
200219
}
201220

202-
return await response.json();
221+
console.log("📱 Adding task to iOS Calendar via .ics download:", task.title);
222+
223+
// Create and download .ics file
224+
const result = await createAndDownloadIcsFile({
225+
id: task.id,
226+
title: task.title,
227+
description: task.description,
228+
dueDate: task.dueDate,
229+
type: task.type,
230+
});
231+
232+
if (result.success) {
233+
return {
234+
success: true,
235+
eventId: result.filename, // Return filename as event identifier
236+
};
237+
} else {
238+
throw new Error("Failed to create calendar file");
239+
}
203240
} catch (error) {
204241
console.error("Error adding to iOS Calendar:", error);
205242
throw error;

0 commit comments

Comments
 (0)