feat: add reminders page, BMad skills upgrade, MCP server refactor

- Add reminders page with navigation support
- Upgrade BMad builder module to skills-based architecture
- Refactor MCP server: extract tools and auth into separate modules
- Add connections cache, custom AI provider support
- Update prisma schema and generated client
- Various UI/UX improvements and i18n updates
- Add service worker for PWA support

Made-with: Cursor
This commit is contained in:
Sepehr Ramezani
2026-04-13 21:02:53 +02:00
parent 18ed116e0d
commit fa7e166f3e
3099 changed files with 397228 additions and 14584 deletions

View File

@@ -56,11 +56,11 @@ export function BatchOrganizationDialog({
})
setSelectedNotes(allNoteIds)
} else {
toast.error(data.error || 'Failed to create organization plan')
toast.error(data.error || t('ai.batchOrganization.error'))
}
} catch (error) {
console.error('Failed to create organization plan:', error)
toast.error('Failed to create organization plan')
toast.error(t('ai.batchOrganization.error'))
} finally {
setLoading(false)
}
@@ -108,7 +108,7 @@ export function BatchOrganizationDialog({
const handleApply = async () => {
if (!plan || selectedNotes.size === 0) {
toast.error('No notes selected')
toast.error(t('ai.batchOrganization.noNotesSelected'))
return
}
@@ -127,18 +127,15 @@ export function BatchOrganizationDialog({
const data = await response.json()
if (data.success) {
toast.success(
t('ai.batchOrganization.success', { count: data.data.movedCount }) ||
`${data.data.movedCount} notes moved successfully`
)
toast.success(t('ai.batchOrganization.success', { count: data.data.movedCount }))
onNotesMoved()
onOpenChange(false)
} else {
toast.error(data.error || 'Failed to apply organization plan')
toast.error(data.error || t('ai.batchOrganization.applyFailed'))
}
} catch (error) {
console.error('Failed to apply organization plan:', error)
toast.error('Failed to apply organization plan')
toast.error(t('ai.batchOrganization.applyFailed'))
} finally {
setApplying(false)
}
@@ -222,7 +219,7 @@ export function BatchOrganizationDialog({
<Checkbox
checked={allSelected}
onCheckedChange={() => toggleNotebookSelection(notebook)}
aria-label={`Select all notes in ${notebook.notebookName}`}
aria-label={t('ai.batchOrganization.selectAllIn', { notebook: notebook.notebookName })}
/>
<div className="flex items-center gap-2">
<span className="text-xl">{notebook.notebookIcon}</span>
@@ -247,7 +244,7 @@ export function BatchOrganizationDialog({
<Checkbox
checked={selectedNotes.has(note.noteId)}
onCheckedChange={() => toggleNoteSelection(note.noteId)}
aria-label={`Select note: ${note.title || 'Untitled'}`}
aria-label={t('ai.batchOrganization.selectNote', { title: note.title || t('notes.untitled') })}
/>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium truncate">
@@ -258,7 +255,7 @@ export function BatchOrganizationDialog({
</p>
<div className="flex items-center gap-2 mt-1">
<span className="text-xs px-2 py-0.5 rounded-full bg-primary/10 text-primary">
{Math.round(note.confidence * 100)}% confidence
{Math.round(note.confidence * 100)}% {t('notebook.confidence')}
</span>
{note.reason && (
<span className="text-xs text-muted-foreground">