Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7b84ffb
Use outlook endpoint
edulelis Oct 9, 2025
ec6ab2f
PR feedback
edulelis Oct 10, 2025
d2665f9
PR feedback
edulelis Oct 16, 2025
e6ed61c
Merge branch 'main' into microsoft-calendar
elie222 Oct 22, 2025
9769179
add microsoft calendar set up notes
elie222 Oct 22, 2025
016ff9a
fix(calendar): fix OAuth callback redirects and standardize error han…
elie222 Oct 22, 2025
f6dbad4
unify google and microsoft calendar connection
elie222 Oct 22, 2025
6545499
get availabilty for ai drafting from microsoft calendars
elie222 Oct 22, 2025
5066979
feat: Add Outlook support to deep-clean feature
salja03-t21 Oct 28, 2025
02c29be
feat(clean): Add backward navigation to deep-clean wizard
salja03-t21 Oct 28, 2025
da6ccc3
fix(ui): Disable premium banner in SideNav for testing
salja03-t21 Oct 28, 2025
984e7a5
fix: Disable PremiumAlertWithData component for testing
salja03-t21 Oct 28, 2025
9e37598
fix: Disable premium check in cleanInbox action for testing
salja03-t21 Oct 28, 2025
4bfb394
Fix: Correct provider property path to use emailAccount.account.provider
salja03-t21 Oct 28, 2025
6366e6d
fix: Make clean preview work with Outlook and improve UX
salja03-t21 Oct 29, 2025
5d36de4
Merge Outlook Deep Clean feature with premium disabled for testing
salja03-t21 Oct 29, 2025
b56c383
fix: Address CoderabbitAI review findings
salja03-t21 Oct 29, 2025
00a1a35
chore: Update cursor rules and refine Outlook clean functionality
salja03-t21 Nov 2, 2025
8abca15
Merge PR #841: Add Outlook Calendar integration
salja03-t21 Nov 2, 2025
fe34f2b
fix: Resolve TypeScript errors after Outlook Calendar merge
salja03-t21 Nov 2, 2025
64adefe
docs: Create implementation plan for email-triggered meeting scheduler
salja03-t21 Nov 2, 2025
22c1ee4
feat: Add email trigger detection for meeting scheduler
salja03-t21 Nov 2, 2025
874e298
feat: Add AI meeting parser for extracting meeting details
salja03-t21 Nov 2, 2025
e46b433
feat: Add meeting availability checker
salja03-t21 Nov 2, 2025
e79eaf3
feat: Implement meeting link generation (Phase 4)
salja03-t21 Nov 2, 2025
3dbc061
feat: Implement calendar event creation (Phase 5)
salja03-t21 Nov 2, 2025
2f22c69
test: Add comprehensive provider validation tests
salja03-t21 Nov 2, 2025
8673874
feat: Add meeting scheduler settings to database schema
salja03-t21 Nov 2, 2025
f7affa8
feat: Add meeting scheduler settings and server actions
salja03-t21 Nov 2, 2025
80d024e
test: Add comprehensive unit tests for meeting scheduler settings val…
salja03-t21 Nov 2, 2025
9526747
feat: Add meeting scheduler settings UI and API
salja03-t21 Nov 2, 2025
2abae54
feat: Add automatic webhook setup and Connect Calendar UI for Meeting…
salja03-t21 Nov 2, 2025
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
5 changes: 2 additions & 3 deletions .cursor/rules/cursor-rules.mdc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: How to add or edit Cursor rules in our project
globs:
alwaysApply: false
globs: .cursor/rules/**/*
alwaysApply: true
---
# Cursor Rules Location

Expand Down Expand Up @@ -63,4 +63,3 @@ function badExample() {
// Implementation not following guidelines
}
```
````
5 changes: 4 additions & 1 deletion .cursor/rules/data-fetching.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
---
description: Fetching data from the API using SWR
globs:
- apps/web/hooks/**/*
- apps/web/app/**/*.tsx
- apps/web/components/**/*
alwaysApply: false
---
# Data Fetching
Expand Down Expand Up @@ -44,4 +47,4 @@ const onSubmit: SubmitHandler<TestRulesInputs> = useCallback(async (data) => {
toastSuccess({ description: "Saved!" });
}
}, []);
```
```
5 changes: 4 additions & 1 deletion .cursor/rules/environment-variables.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
---
description: Add environment variable
globs:
- apps/web/env.ts
- apps/web/.env.example
- turbo.json
alwaysApply: false
---
# Environment Variables
Expand Down Expand Up @@ -83,4 +86,4 @@ examples:
references:
- apps/web/env.ts
- apps/web/.env.example
- turbo.json
- turbo.json
7 changes: 6 additions & 1 deletion .cursor/rules/features/cleaner.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
---
description:
description: Inbox Cleaner feature documentation
globs:
- apps/web/utils/actions/clean.ts
- apps/web/app/api/clean/**/*
- apps/web/app/(app)/*/clean/**/*
- apps/web/prisma/schema.prisma
- apps/web/utils/redis/clean.ts
alwaysApply: false
---
## Inbox Cleaner
Expand Down
5 changes: 5 additions & 0 deletions .cursor/rules/features/delayed-actions.mdc
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
description: Delayed Actions feature documentation
globs:
alwaysApply: false
---
# Delayed Actions Feature

## Overview
Expand Down
3 changes: 1 addition & 2 deletions .cursor/rules/features/digest.mdc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description:
description: Digest feature documentation
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the closing ``` leaves the final TypeScript code block unterminated, which breaks Markdown rendering for the remainder of the document.

Prompt for AI agents
Address the following comment on .cursor/rules/features/digest.mdc at line 2:

<comment>Removing the closing ``` leaves the final TypeScript code block unterminated, which breaks Markdown rendering for the remainder of the document.</comment>

<file context>
@@ -1,5 +1,5 @@
 ---
-description: 
+description: Digest feature documentation
 globs: 
 alwaysApply: false
</file context>
Fix with Cubic

globs:
alwaysApply: false
---
Expand Down Expand Up @@ -288,4 +288,3 @@ const isDigestEnabled = useFeatureFlagEnabled("digest-emails");
coldEmailDigest: boolean, // Include cold emails in digest
digestSchedule: Schedule // When to send digests
}
```
2 changes: 1 addition & 1 deletion .cursor/rules/features/knowledge.mdc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description:
description: Knowledge Base feature documentation
globs:
alwaysApply: false
---
Expand Down
162 changes: 1 addition & 161 deletions .cursor/rules/features/schedule.mdc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description:
description: Schedule feature documentation
globs:
alwaysApply: false
---
Expand Down Expand Up @@ -311,158 +311,6 @@ const userTime = new Date().toLocaleString("en-US", {

---

## Testing & Development

### Testing Schedule Calculations

```typescript
import { calculateNextScheduleDate } from '@/utils/schedule';

describe('Schedule', () => {
it('calculates daily schedule correctly', () => {
const next = calculateNextScheduleDate({
intervalDays: 1,
occurrences: 1,
timeOfDay: new Date('2023-01-01T11:00:00')
}, new Date('2023-01-01T10:00:00'));

expect(next).toEqual(new Date('2023-01-01T11:00:00'));
});

it('handles multiple occurrences per week', () => {
const next = calculateNextScheduleDate({
intervalDays: 7,
occurrences: 3,
timeOfDay: new Date('2023-01-01T09:00:00')
}, new Date('2023-01-01T08:00:00'));

// Should return first slot of the week
expect(next.getHours()).toBe(9);
});
});
```

### Development Workflow

1. **Design the schedule pattern** - What schedule do you need?
2. **Test with calculateNextScheduleDate** - Verify the logic works
3. **Add UI with SchedulePicker** - Let users configure it
4. **Implement the recurring job** - Use the calculated dates
5. **Test edge cases** - Timezone changes, DST, month boundaries

---

## Common Patterns & Best Practices

### Updating Schedule Settings

```typescript
// Always recalculate next occurrence when settings change
const updateSchedule = async (newSchedule: Schedule) => {
const nextOccurrence = calculateNextScheduleDate(newSchedule);

await prisma.schedule.update({
where: { emailAccountId },
data: {
...newSchedule,
nextOccurrenceAt: nextOccurrence
}
});
};
```

### Processing Due Events

```typescript
// Standard pattern for processing scheduled events
const processDueEvents = async () => {
const dueItems = await prisma.feature.findMany({
where: {
nextOccurrenceAt: { lte: new Date() }
},
include: { frequency: true }
});

for (const item of dueItems) {
// Process the event
await processEvent(item);

// Calculate and update next occurrence
const nextDate = calculateNextScheduleDate(item.schedule);
await prisma.feature.update({
where: { id: item.id },
data: {
lastOccurrenceAt: new Date(),
nextOccurrenceAt: nextDate
}
});
}
};
```

### Form Integration

```typescript
// Standard form setup with SchedulePicker
const ScheduleSettingsForm = () => {
const form = useForm({
defaultValues: getInitialScheduleProps(currentSchedule)
});

const onSubmit = async (data) => {
const schedule = mapToSchedule(data);
await updateScheduleAction(schedule);
};

return (
<form onSubmit={form.handleSubmit(onSubmit)}>
<SchedulePicker
value={form.watch()}
onChange={(value) => form.reset(value)}
/>
</form>
);
};
```

---

## Troubleshooting

### Common Issues

**Next occurrence not updating:**
- Ensure you're calling `calculateNextScheduleDate` after each event
- Check that `lastOccurrenceAt` is being updated
- Verify timezone handling is consistent

**FrequencyPicker not saving correctly:**
- Use `mapToSchedule` to convert form data
- Check that all required fields are present
- Validate bitmask values for `daysOfWeek`

**Unexpected scheduling behavior:**
- Test with fixed dates instead of `new Date()`
- Check for DST transitions affecting time calculations
- Verify `intervalDays` and `occurrences` are positive integers

### Debug Tools

```typescript
// Debug schedule calculation
const debugSchedule = (schedule: Schedule, fromDate: Date) => {
console.log('Input:', { schedule, fromDate });

const next = calculateNextScheduleDate(schedule, fromDate);
console.log('Next occurrence:', next);

const timeDiff = next.getTime() - fromDate.getTime();
console.log('Time until next:', timeDiff / (1000 * 60 * 60), 'hours');
};
```

---

## File Reference

### Core Implementation
Expand All @@ -481,11 +329,3 @@ const debugSchedule = (schedule: Schedule, fromDate: Date) => {
### Validation & Types
- `apps/web/app/api/ai/digest/validation.ts` - API validation schemas
- `apps/web/types/schedule.ts` - TypeScript type definitions

---

## Related Documentation

- **[Digest Feature](mdc:digest.mdc)** - Primary use case for Schedule
- **[Prisma Documentation](mdc:https:/prisma.io/docs)** - Database schema patterns
- **[date-fns Documentation](mdc:https:/date-fns.org)** - Date manipulation utilities used internally
2 changes: 2 additions & 0 deletions .cursor/rules/form-handling.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
description: Form handling
globs:
- apps/web/app/**/*.tsx
- apps/web/components/**/*
alwaysApply: false
---
# Form Handling
Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/fullstack-workflow.mdc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
description: Complete fullstack workflow combining GET API routes, server actions, SWR data fetching, and form handling. Use when building features that need both data fetching and mutations from API to UI.
globs:
alwaysApply: false
---
# Fullstack Workflow
Expand Down Expand Up @@ -275,4 +276,3 @@ apps/web/
- [Data Fetching with SWR](mdc:.cursor/rules/data-fetching.mdc)
- [Form Handling](mdc:.cursor/rules/form-handling.mdc)
- [Server Actions](mdc:.cursor/rules/server-actions.mdc)

2 changes: 1 addition & 1 deletion .cursor/rules/get-api-route.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Guidelines for implementing GET API routes in Next.js
globs:
globs: apps/web/app/api/**/route.ts
alwaysApply: false
---
# GET API Route Guidelines
Expand Down
4 changes: 4 additions & 0 deletions .cursor/rules/gmail-api.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
---
description: Guidelines for working with Gmail API
globs:
- apps/web/utils/gmail/**/*
- apps/web/utils/outlook/**/*
- apps/web/app/api/google/**/*
- apps/web/app/api/microsoft/**/*
alwaysApply: false
---
# Gmail API Usage
Expand Down
3 changes: 3 additions & 0 deletions .cursor/rules/hooks.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
---
description: React hooks
globs:
- apps/web/hooks/**/*
- apps/web/app/**/*.tsx
- apps/web/components/**/*
alwaysApply: false
---
# Custom Hook Guidelines
Expand Down
4 changes: 2 additions & 2 deletions .cursor/rules/installing-packages.mdc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: How to install packages
globs:
alwaysApply: false
globs: null
alwaysApply: true
---
- Use `pnpm`.
- Don't install in root. Install in `apps/web`:
Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/llm-test.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Guidelines for writing tests for LLM-related functionality
globs:
globs: apps/web/__tests__/**/*
alwaysApply: false
---
# LLM Testing Guidelines
Expand Down
3 changes: 3 additions & 0 deletions .cursor/rules/llm.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
---
description: Guidelines for implementing LLM (Language Model) functionality in the application
globs:
- apps/web/utils/ai/**/*
- apps/web/utils/llms/**/*
- apps/web/__tests__/**/*
alwaysApply: false
---
# LLM Implementation Guidelines
Expand Down
4 changes: 3 additions & 1 deletion .cursor/rules/logging.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
description: How to do backend logging
globs:
- apps/web/utils/**/*
- apps/web/app/api/**/*
alwaysApply: false
---
# Logging
Expand All @@ -25,4 +27,4 @@ const logger = createScopedLogger("action/rules").with({ userId: user.id });
logger.log("Created rule");
```

Don't use `.with()` for a global logger. Only use within a specific function.
Don't use `.with()` for a global logger. Only use within a specific function.
4 changes: 2 additions & 2 deletions .cursor/rules/notes.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description:
description: General development notes
globs:
alwaysApply: true
---
Do not try and run the project via `dev` or `build` command unless I explicitly ask you to.
Do not try and run the project via `dev` or `build` command unless I explicitly ask you to.
4 changes: 2 additions & 2 deletions .cursor/rules/page-structure.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Page structure
globs:
globs: apps/web/app/(app)/**/*
alwaysApply: false
---
# Page Structure
Expand All @@ -9,4 +9,4 @@ alwaysApply: false
- Components for the page are either put in `page.tsx`, or in the `apps/web/app/(app)/PAGE_NAME` folder
- Pages are Server components so you can load data into them directly
- If we're in a deeply nested component we will use `swr` to fetch via API
- If you need to use `onClick` in a component, that component is a client component and file must start with `use client`
- If you need to use `onClick` in a component, that component is a client component and file must start with `use client`
Loading