mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:21:09 +02:00
Projects included: - maerchenzauber (NestJS backend + Expo mobile + SvelteKit web + Astro landing) - manacore (Expo mobile + SvelteKit web + Astro landing) - manadeck (NestJS backend + Expo mobile + SvelteKit web) - memoro (Expo mobile + SvelteKit web + Astro landing) This commit preserves the current state before monorepo restructuring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
278 lines
No EOL
7.9 KiB
Markdown
278 lines
No EOL
7.9 KiB
Markdown
# Spaces Feature Documentation
|
|
|
|
## Overview
|
|
|
|
Spaces in Memoro allow users to organize their memories and memos into logical containers. This feature provides a way to categorize content, manage access, and facilitate organization of user data.
|
|
|
|
## Architecture
|
|
|
|
The Spaces feature uses a centralized approach for data management with fast local access:
|
|
|
|
1. **Express Backend API**: Serves as the source of truth for space management
|
|
2. **Memoro App (Client)**: Interfaces with the Express Backend API
|
|
3. **Supabase Database**: Used by both the Express Backend and the app for data storage and retrieval
|
|
|
|
This architecture allows the app to perform operations through the Express Backend API, which then directly updates the Supabase database. This ensures a single source of truth while still enabling fast data access.
|
|
|
|
## Implementation Details
|
|
|
|
### Database Schema
|
|
|
|
In Memoro's local Supabase database:
|
|
|
|
```sql
|
|
-- Spaces table
|
|
CREATE TABLE public.spaces (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name TEXT NOT NULL,
|
|
description TEXT DEFAULT '',
|
|
color TEXT DEFAULT '#4CAF50',
|
|
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
is_default BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Junction table linking memos to spaces
|
|
CREATE TABLE public.memo_spaces (
|
|
memo_id UUID NOT NULL REFERENCES public.memos(id) ON DELETE CASCADE,
|
|
space_id UUID NOT NULL REFERENCES public.spaces(id) ON DELETE CASCADE,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
PRIMARY KEY (memo_id, space_id)
|
|
);
|
|
```
|
|
|
|
The schema includes foreign key constraints to ensure referential integrity between the spaces, memos, and user tables.
|
|
|
|
### API Integration
|
|
|
|
The app integrates with the Memoro API:
|
|
|
|
1. **API Endpoints**:
|
|
- `GET /api/memoro/spaces` - List all spaces for the authenticated user
|
|
- `GET /api/memoro/spaces/:id` - Get space details
|
|
- `POST /api/memoro/spaces` - Create a new space
|
|
- `PUT /api/memoro/spaces/:id` - Update a space
|
|
- `DELETE /api/memoro/spaces/:id` - Delete a space
|
|
- `GET /api/memoro/spaces/:spaceId/memos` - Get all memos for a specific space
|
|
- `POST /api/memoro/spaces/memos/link` - Link a memo to a space
|
|
- `DELETE /api/memoro/spaces/memos/unlink` - Unlink a memo from a space
|
|
|
|
### Space-Memo Relationship
|
|
|
|
Spaces can contain multiple memos, and memos can belong to multiple spaces. This is a many-to-many relationship implemented through the `memo_spaces` junction table. The API provides specific endpoints to manage these relationships:
|
|
|
|
- **Retrieving memos in a space**: Using `GET /api/memoro/spaces/:spaceId/memos`
|
|
- **Linking a memo to a space**: Using `POST /api/memoro/spaces/memos/link`
|
|
- **Unlinking a memo from a space**: Using `DELETE /api/memoro/spaces/memos/unlink`
|
|
|
|
### Data Structures
|
|
|
|
The Space interface reflects the updated API response structure:
|
|
|
|
```typescript
|
|
export interface Space {
|
|
id: string;
|
|
name: string;
|
|
description?: string;
|
|
memoCount?: number;
|
|
isDefault?: boolean;
|
|
color?: string;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
owner_id?: string;
|
|
app_id?: string;
|
|
credits?: number;
|
|
roles?: {
|
|
members: {
|
|
[userId: string]: {
|
|
role: string;
|
|
added_at: string;
|
|
added_by: string;
|
|
};
|
|
};
|
|
};
|
|
apps?: {
|
|
name: string;
|
|
slug: string;
|
|
};
|
|
}
|
|
```
|
|
|
|
And the Memo interface for space-specific memos:
|
|
|
|
```typescript
|
|
export interface Memo {
|
|
id: string;
|
|
title: string;
|
|
user_id: string;
|
|
source?: any;
|
|
style?: any;
|
|
is_pinned?: boolean;
|
|
is_archived?: boolean;
|
|
is_public?: boolean;
|
|
metadata?: any;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
}
|
|
```
|
|
|
|
### Authentication
|
|
|
|
Custom JWT-based authentication is used throughout:
|
|
|
|
1. User authenticates with the Memoro middleware (mana-core)
|
|
2. JWT token contains a `sub` claim with the user ID
|
|
3. This token is used for all API requests
|
|
4. All API endpoints require a valid JWT token
|
|
|
|
### Client Implementation
|
|
|
|
The app uses:
|
|
- `spaceService.ts`: Service for space operations, including memo management
|
|
- `useSpaces.ts`: Hook for React components
|
|
- `SpaceContext.tsx`: Context provider for the app
|
|
- `SpacesScreen.tsx`: Main UI for space management
|
|
- `[id].tsx`: Space detail view showing space info and all associated memos
|
|
|
|
## User Interface
|
|
|
|
The Spaces UI includes:
|
|
|
|
### Spaces List Screen
|
|
- List of spaces with customizable colors
|
|
- Create/edit/delete functionality
|
|
- Space selection for filtering memos
|
|
- Visual indication of the active space
|
|
|
|
### Space Detail Screen
|
|
- Shows space details (name, description, color, etc.)
|
|
- Displays all memos associated with the space
|
|
- Supports adding new memos to the space
|
|
- Handles error cases gracefully with retry mechanisms
|
|
|
|
## Error Handling
|
|
|
|
The system handles several error cases:
|
|
- Network failures during API requests
|
|
- Authentication errors
|
|
- Permission issues
|
|
- Database constraints
|
|
|
|
Error handling improvements:
|
|
- Error messages are properly displayed in the UI
|
|
- Retry mechanisms for failed requests
|
|
- Cleanup functions to prevent memory leaks and state updates after component unmount
|
|
- Mock data support for development/testing
|
|
|
|
### Error Handling Example
|
|
|
|
The Space detail view implements robust error handling:
|
|
|
|
```typescript
|
|
// Error handling for memo loading
|
|
useEffect(() => {
|
|
// Create a flag to prevent state updates after unmount
|
|
let isMounted = true;
|
|
|
|
const fetchSpaceMemos = async () => {
|
|
if (!id) return;
|
|
|
|
try {
|
|
setLoadingMemos(true);
|
|
setMemosError(null);
|
|
|
|
// Fetch memos for this space
|
|
const memos = await spaceContext.getSpaceMemos(id);
|
|
|
|
// Only update state if component is still mounted
|
|
if (isMounted) {
|
|
setSpaceMemos(memos);
|
|
}
|
|
|
|
} catch (err) {
|
|
console.error('Error fetching space memos:', err);
|
|
|
|
// Only update state if component is still mounted
|
|
if (isMounted) {
|
|
setMemosError('Failed to load memos for this space');
|
|
}
|
|
} finally {
|
|
// Only update state if component is still mounted
|
|
if (isMounted) {
|
|
setLoadingMemos(false);
|
|
}
|
|
}
|
|
};
|
|
|
|
fetchSpaceMemos();
|
|
|
|
// Cleanup function to prevent state updates after unmount
|
|
return () => {
|
|
isMounted = false;
|
|
};
|
|
}, [id]);
|
|
```
|
|
|
|
UI for error states:
|
|
```jsx
|
|
{loadingMemos ? (
|
|
<LoadingIndicator />
|
|
) : memosError ? (
|
|
<ErrorView
|
|
message={memosError}
|
|
onRetry={() => {
|
|
setLoadingMemos(true);
|
|
setMemosError(null);
|
|
// Re-render triggers the useEffect again
|
|
}}
|
|
/>
|
|
) : (
|
|
<MemoList memos={spaceMemos} spaceId={id} />
|
|
)}
|
|
```
|
|
|
|
## Development and Testing Support
|
|
|
|
The implementation includes development aids:
|
|
|
|
```typescript
|
|
// Mock data support for development
|
|
async getSpaceMemos(spaceId: string): Promise<Memo[]> {
|
|
// For development/testing, use mock data if API is not available
|
|
const USE_MOCK_DATA = process.env.EXPO_PUBLIC_USE_MOCK_DATA === 'true';
|
|
|
|
if (USE_MOCK_DATA) {
|
|
console.debug('Using mock data for space memos');
|
|
return [];
|
|
}
|
|
|
|
// Regular API call implementation
|
|
// ...
|
|
}
|
|
```
|
|
|
|
## Navigation
|
|
|
|
Navigation between spaces-related screens:
|
|
- From spaces list to space detail view via `router.push(`/(protected)/(space)/${spaceId}`)`
|
|
- Add memo to space via navigation to memo creation with space ID in params
|
|
- Back to spaces list via built-in back navigation
|
|
|
|
## Future Enhancements
|
|
|
|
Potential improvements for the spaces feature:
|
|
1. **Offline Support**: Caching space data for offline use
|
|
2. **Batch Operations**: Moving multiple memos between spaces
|
|
3. **Advanced Filtering**: Filter memos by multiple spaces or other criteria
|
|
4. **Space Sharing**: Allowing users to share spaces with other users
|
|
5. **Nested Spaces**: Implementing hierarchical space organization
|
|
|
|
## Maintenance and Troubleshooting
|
|
|
|
Common issues and solutions:
|
|
|
|
1. **API Communication Errors**: Check console logs for detailed error messages
|
|
2. **Authentication Issues**: Verify JWT token format and claims
|
|
3. **Performance Concerns**: Monitor API call performance
|
|
4. **Mock Data**: Use `EXPO_PUBLIC_USE_MOCK_DATA=true` for testing without API |