Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions client/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,4 +330,52 @@ export class API {
});
}

// University calendar preferences
public static async getCalendarPreferences(): Promise<{
global: any;
event_types: Record<string, any>;
uni_cal_categories: Record<string, any>;
}> {
const baseUrl = await this.getBaseUrl();
const token = await this.getJwtToken();
const response = await fetch(`${baseUrl}/calendar_preferences`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.json();
}

public static async setUniCalCategoryPreference(category: string, preferences: {
color_id?: string;
title_template?: string;
description_template?: string;
}): Promise<any> {
const baseUrl = await this.getBaseUrl();
const token = await this.getJwtToken();
const response = await fetch(`${baseUrl}/calendar_preferences/uni_cal:${category}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ calendar_preference: preferences })
});
return response.json();
}

// Set color for all university calendar categories at once
// colorId should be a Google Calendar color ID (1-11)
public static async setAllUniCalCategoriesColor(colorId: string): Promise<void> {
const categories = [
'holiday', 'term_dates', 'registration', 'deadline', 'finals',
'graduation', 'academic', 'campus_event', 'meeting', 'exhibit',
'announcement', 'other'
];
await Promise.all(
categories.map(cat => this.setUniCalCategoryPreference(cat, { color_id: colorId }))
);
}

}
65 changes: 65 additions & 0 deletions client/src/lib/components/Settings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@
import { Button, SelectOutlined, snackbar, Switch } from "m3-svelte";
import { onMount } from "svelte";

// Google Calendar color ID to hex mapping
const COLOR_ID_TO_HEX: Record<string, string> = {
"1": "#7986cb", // Lavender
"2": "#33b679", // Sage
"3": "#8e24aa", // Grape
"4": "#e67c73", // Flamingo
"5": "#f6bf26", // Banana
"6": "#f4511e", // Tangerine
"7": "#039be5", // Peacock
"8": "#616161", // Graphite
"9": "#3f51b5", // Blueberry
"10": "#0b8043", // Basil
"11": "#d50000", // Tomato
};

const HEX_TO_COLOR_ID: Record<string, string> = Object.fromEntries(
Object.entries(COLOR_ID_TO_HEX).map(([id, hex]) => [hex, id])
);

let userSettings = $state<UserSettings | undefined>(undefined);
let email = $state<string | undefined>(undefined);
let currentEnvironment = $state<Environment>('prod');
Expand All @@ -19,6 +38,7 @@
let showEnvSwitcher = $state<boolean>(false);
let showClearDataButton = $state<boolean>(false);
let isRefreshingFlags = $state<boolean>(false);
let uniCalColor = $state<string>("#616161"); // Default to Graphite

$effect(() => {
userSettings = $storedUserSettings;
Expand Down Expand Up @@ -74,6 +94,19 @@
} catch (e) {
console.error('Failed to fetch connected accounts:', e);
}

// Fetch uni cal color preference
try {
const calPrefs = await API.getCalendarPreferences();
// Check if any uni_cal_category has a color set (they should all be the same)
const firstCategory = Object.values(calPrefs.uni_cal_categories || {})[0];
if (firstCategory?.color_id) {
const colorId = String(firstCategory.color_id);
uniCalColor = COLOR_ID_TO_HEX[colorId] || "#616161";
}
} catch (e) {
// Calendar preferences might not exist yet, that's okay
}
} catch (error) {
console.error('Failed to load settings:', error);
}
Expand Down Expand Up @@ -142,6 +175,15 @@
}
}

const uniCalColorGetterSetter = {
get value() { return uniCalColor; },
set value(value: string) {
uniCalColor = value;
const colorId = HEX_TO_COLOR_ID[value] || "8"; // Default to Graphite
API.setAllUniCalCategoriesColor(colorId);
}
}

function toggleUniversityCategory(categoryId: string) {
if (!userSettings) return;
const currentCategories = userSettings.university_event_categories ?? [];
Expand Down Expand Up @@ -476,6 +518,29 @@
</div>
</div>

<div class="flex flex-row gap-3 items-center justify-between">
<h2 class="text-md font-bold">University Events Color</h2>
<div class="flex flex-row gap-2 items-center">
<div class="w-6 h-6 rounded-full border-2 border-outline" style="background-color: {uniCalColor};"></div>
<SelectOutlined label=""
options={[
{ text: "Tomato", value: "#d50000" },
{ text: "Flamingo", value: "#e67c73" },
{ text: "Tangerine", value: "#f4511e" },
{ text: "Banana", value: "#f6bf26" },
{ text: "Sage", value: "#33b679" },
{ text: "Basil", value: "#0b8043" },
{ text: "Peacock", value: "#039be5" },
{ text: "Blueberry", value: "#3f51b5" },
{ text: "Lavender", value: "#7986cb" },
{ text: "Grape", value: "#8e24aa" },
{ text: "Graphite", value: "#616161" },
]}
bind:value={uniCalColorGetterSetter.value}
/>
</div>
</div>

{#if syncUniversityEventsValue && availableCategories.length > 0}
<div class="flex flex-col gap-2 ml-2 pl-4 border-l-2 border-outline-variant">
<p class="text-sm text-outline font-medium">Select event types to sync:</p>
Expand Down
Loading