diff --git a/package-lock.json b/package-lock.json index 2e60fc0..5329c83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -998,7 +998,6 @@ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1658,7 +1657,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -2359,7 +2357,6 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -2681,7 +2678,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -2749,7 +2745,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -3439,7 +3434,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3512,7 +3506,6 @@ "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -3676,7 +3669,6 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.24.tgz", "integrity": "sha512-uTHDOpVQTMjcGgrqFPSb8iO2m1DUvo+WbGqoXQz8Y1CeBYQ0FXf2z1gLRaBtHjlRz7zZUBHxjVB5VTLzYkvftg==", "license": "MIT", - "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.24", "@vue/compiler-sfc": "3.5.24", @@ -3705,7 +3697,6 @@ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.3.tgz", "integrity": "sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==", "license": "MIT", - "peer": true, "dependencies": { "@vue/devtools-api": "^6.6.4" }, diff --git a/src/App.vue b/src/App.vue index d4f3c0c..909def4 100644 --- a/src/App.vue +++ b/src/App.vue @@ -8,13 +8,14 @@ import InputForm from './components/InputForm.vue' import ResultSummary from './components/ResultSummary.vue' import Timeline from './components/Timeline.vue' import { useAppStore } from './stores/app' -import { createUnemploymentICS, downloadIcsFile } from './utils/ics' +import { createUnemploymentICS, createStemEvaluationICS, downloadIcsFile } from './utils/ics' const store = useAppStore() const showHelpModal = ref(false) type ToastType = 'success' | 'error' const copyStatus = ref<'idle' | 'copied' | 'error'>('idle') const exportStatus = ref<'idle' | 'success' | 'error'>('idle') +const stemEvalStatus = ref<'idle' | 'success' | 'error'>('idle') const toasts = ref<{ id: number; message: string; type: ToastType }[]>([]) let tempTimer: number | null = null @@ -123,6 +124,29 @@ async function exportDeadlines() { }, 3000) } } + +async function exportStemEvaluations() { + if (!store.stemPeriod) return + if (tempTimer) { + clearTimeout(tempTimer) + tempTimer = null + } + try { + const ics = createStemEvaluationICS(store.stemPeriod.startDate) + if (!ics) throw new Error('Missing STEM OPT period') + downloadIcsFile(ics, 'stem-opt-evaluations.ics') + stemEvalStatus.value = 'success' + pushToast('STEM evaluation reminders downloaded', 'success') + } catch (error) { + console.error('Failed to export STEM evaluation ICS', error) + stemEvalStatus.value = 'error' + pushToast('Failed to export STEM evaluation reminders', 'error') + } finally { + tempTimer = window.setTimeout(() => { + stemEvalStatus.value = 'idle' + }, 3000) + } +}