diff --git a/dashboards/tracker-web/eslint.config.js b/dashboards/tracker-web/eslint.config.js deleted file mode 100644 index ff91dd3f..00000000 --- a/dashboards/tracker-web/eslint.config.js +++ /dev/null @@ -1,104 +0,0 @@ -import js from '@eslint/js'; -import tseslint from '@typescript-eslint/eslint-plugin'; -import tsparser from '@typescript-eslint/parser'; - -export default [ - { - ignores: [ - 'dist/**', - 'node_modules/**', - 'coverage/**', - '*.config.js', - '*.config.ts', - '.next/**', - 'out/**', - ], - }, - js.configs.recommended, - { - files: ['**/*.ts', '**/*.tsx'], - languageOptions: { - parser: tsparser, - parserOptions: { - ecmaVersion: 2022, - sourceType: 'module', - }, - globals: { - process: 'readonly', - Buffer: 'readonly', - __dirname: 'readonly', - __filename: 'readonly', - Headers: 'readonly', - TextEncoder: 'readonly', - TextDecoder: 'readonly', - RequestInit: 'readonly', - HeadersInit: 'readonly', - Response: 'readonly', - Request: 'readonly', - fetch: 'readonly', - console: 'readonly', - performance: 'readonly', - AbortSignal: 'readonly', - expect: 'readonly', - describe: 'readonly', - it: 'readonly', - test: 'readonly', - beforeEach: 'readonly', - afterEach: 'readonly', - beforeAll: 'readonly', - afterAll: 'readonly', - crypto: 'readonly', - localStorage: 'readonly', - sessionStorage: 'readonly', - ReactNode: 'readonly', - React: 'readonly', - JSX: 'readonly', - window: 'readonly', - document: 'readonly', - navigator: 'readonly', - setTimeout: 'readonly', - clearTimeout: 'readonly', - setInterval: 'readonly', - clearInterval: 'readonly', - URL: 'readonly', - URLSearchParams: 'readonly', - confirm: 'readonly', - alert: 'readonly', - HTMLDivElement: 'readonly', - HTMLInputElement: 'readonly', - HTMLButtonElement: 'readonly', - MessageEvent: 'readonly', - }, - }, - plugins: { - '@typescript-eslint': tseslint, - }, - rules: { - // TypeScript specific rules - '@typescript-eslint/no-unused-vars': [ - 'error', - { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' }, - ], - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/no-explicit-any': 'warn', - - // General rules - 'no-console': 'warn', - 'no-debugger': 'error', - 'prefer-const': 'error', - 'no-var': 'error', - 'no-unused-vars': 'off', // Use TypeScript version - - // Import rules - disabled for now - // 'sort-imports': ['error', { ignoreDeclarationSort: true }], - }, - }, - { - files: ['next.config.ts'], - rules: { - '@typescript-eslint/no-var-requires': 'off', - '@typescript-eslint/no-require-imports': 'off', - }, - }, -]; diff --git a/dashboards/tracker-web/src/app/roadmap/page.tsx b/dashboards/tracker-web/src/app/roadmap/page.tsx index 29016fdd..df13cec7 100644 --- a/dashboards/tracker-web/src/app/roadmap/page.tsx +++ b/dashboards/tracker-web/src/app/roadmap/page.tsx @@ -67,6 +67,7 @@ export default function RoadmapPage() { const [items, setItems] = useState([]); const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); + const [loadError, setLoadError] = useState(''); const [search, setSearch] = useState(''); const [typeFilter, setTypeFilter] = useState(''); const [view, setView] = useState<'board' | 'list'>('board'); @@ -88,6 +89,7 @@ export default function RoadmapPage() { const [showEmailPrompt, setShowEmailPrompt] = useState(false); const [pendingVoteId, setPendingVoteId] = useState(null); const [votedItems, setVotedItems] = useState>(new Set()); + const [voteError, setVoteError] = useState(''); useEffect(() => { if (typeof window !== 'undefined') { @@ -100,6 +102,7 @@ export default function RoadmapPage() { const fetchData = useCallback(async () => { setLoading(true); + setLoadError(''); try { const params: Record = { sortBy: 'voteCount', @@ -112,7 +115,7 @@ export default function RoadmapPage() { setItems(itemsRes.items); setStats(statsRes); } catch (err) { - console.error('Failed to load roadmap:', err); + setLoadError(err instanceof Error ? err.message : 'Failed to load roadmap'); } finally { setLoading(false); } @@ -132,6 +135,7 @@ export default function RoadmapPage() { }; const doVote = async (itemId: string, email: string) => { + setVoteError(''); try { const res = await publicVote(itemId, email); setItems(prev => prev.map(i => (i.id === itemId ? { ...i, voteCount: res.voteCount } : i))); @@ -144,7 +148,7 @@ export default function RoadmapPage() { setVotedItems(newVoted); localStorage.setItem('roadmap_voted', JSON.stringify([...newVoted])); } catch (err) { - console.error('Vote failed:', err); + setVoteError(err instanceof Error ? err.message : 'Vote failed'); } }; @@ -217,6 +221,17 @@ export default function RoadmapPage() {
+ {loadError ? ( +
+ {loadError} +
+ ) : null} + {voteError ? ( +
+ {voteError} +
+ ) : null} + {/* Stats bar */} {stats && (