- Consolidated duplicate UndoManagers to single instance - Fixed connection promise to only resolve on 'connected' status - Fixed WebSocketProvider import (WebsocketProvider) - Added proper doc.destroy() cleanup - Renamed isPresenceInitialized property to avoid conflict Co-Authored-By: Paperclip <noreply@paperclip.ing>
95 lines
3.5 KiB
TypeScript
95 lines
3.5 KiB
TypeScript
import { Component } from 'solid-js';
|
|
import { A } from '@solidjs/router';
|
|
import { useAuth } from '../../lib/auth';
|
|
import { createProjectService } from '../../lib/projects/service';
|
|
|
|
export const Dashboard: Component = () => {
|
|
const auth = useAuth();
|
|
const projectService = createProjectService();
|
|
|
|
return (
|
|
<div class="freno-dashboard">
|
|
<div class="freno-welcome">
|
|
<h1>Welcome back, {auth().user?.name?.split(' ')[0] || 'there'}!</h1>
|
|
<p>Here's what's happening with your projects.</p>
|
|
</div>
|
|
|
|
<div class="freno-stats-grid">
|
|
<div class="freno-stat-card">
|
|
<div class="freno-stat-value">{projectService.projects().length}</div>
|
|
<div class="freno-stat-label">Total Projects</div>
|
|
</div>
|
|
<div class="freno-stat-card">
|
|
<div class="freno-stat-value">
|
|
{projectService.projects().filter((p) => p.status === 'active').length}
|
|
</div>
|
|
<div class="freno-stat-label">Active</div>
|
|
</div>
|
|
<div class="freno-stat-card">
|
|
<div class="freno-stat-value">
|
|
{projectService.projects().filter((p) => p.status === 'draft').length}
|
|
</div>
|
|
<div class="freno-stat-label">Drafts</div>
|
|
</div>
|
|
<div class="freno-stat-card">
|
|
<div class="freno-stat-value">
|
|
{projectService.projects().filter((p) => p.collaborators.length > 0).length}
|
|
</div>
|
|
<div class="freno-stat-label">Shared</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="freno-section">
|
|
<div class="freno-section-header">
|
|
<h2>Recent Projects</h2>
|
|
<A href="/projects/new" class="freno-btn freno-btn-primary">
|
|
+ New Project
|
|
</A>
|
|
</div>
|
|
|
|
<div class="freno-project-grid">
|
|
{projectService.projects().length === 0 ? (
|
|
<div class="freno-empty-state">
|
|
<div class="freno-empty-icon">📝</div>
|
|
<h3>No projects yet</h3>
|
|
<p>Create your first project to start writing collaboratively.</p>
|
|
<A href="/projects/new" class="freno-btn freno-btn-primary">
|
|
Create Project
|
|
</A>
|
|
</div>
|
|
) : (
|
|
projectService.projects().slice(0, 6).map((project) => (
|
|
<A href={`/projects/${project.id}`} class="freno-project-card">
|
|
<div class="freno-project-card-header">
|
|
<h3>{project.name}</h3>
|
|
<span class={`freno-badge freno-badge-${project.status}`}>
|
|
{project.status}
|
|
</span>
|
|
</div>
|
|
<p class="freno-project-card-desc">{project.description}</p>
|
|
<div class="freno-project-card-footer">
|
|
<div class="freno-collaborators">
|
|
{project.collaborators.slice(0, 3).map((_, i) => (
|
|
<div class="freno-avatar-small" style={`--i: ${i}`}>
|
|
{String.fromCharCode(65 + i)}
|
|
</div>
|
|
))}
|
|
{project.collaborators.length > 3 && (
|
|
<div class="freno-avatar-more">
|
|
+{project.collaborators.length - 3}
|
|
</div>
|
|
)}
|
|
</div>
|
|
<span class="freno-date">
|
|
{new Date(project.updatedAt).toLocaleDateString()}
|
|
</span>
|
|
</div>
|
|
</A>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|