Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,31 @@ cp apps/web/env.example apps/web/.env.local
# Start the web application
pnpm dev:web

# Start the Nest API (fixture-backed common data; default :3001)
pnpm --filter @worksight/common build
pnpm dev:api

# Start the documentation site
pnpm dev:docs

# Start both applications
# Start both web + docs (turbo)
pnpm dev

# MVP E2E demo: API + web with shared common fixtures (see docs/mvp/DEMO.md)
pnpm demo
```

Open:

- **Web App**: <http://localhost:3000>
- **E2E demo page**: <http://localhost:3000/demo> (requires API on :3001)
- **API**: <http://localhost:3001> (Swagger at `/api`)
- **Documentation**: <http://localhost:5173>

> Demo data is **fixture-backed** from `@worksight/common` — not Supabase. Set
> `NEXT_PUBLIC_USE_API=true` and `NEXT_PUBLIC_API_URL=http://localhost:3001` so
> dashboard/admin pages call Nest instead of in-process fixtures.

## 📦 Available Scripts

### Root Scripts
Expand Down
19 changes: 17 additions & 2 deletions apps/api/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import { ClassSerializerInterceptor } from '@nestjs/common';
import { ClassSerializerInterceptor, Logger } from '@nestjs/common';
import { NestFactory, Reflector } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';

async function bootstrap() {
const app = await NestFactory.create(AppModule);
const logger = new Logger('Bootstrap');
const port = Number(process.env.PORT ?? 3001);
const corsOrigins = (process.env.CORS_ORIGINS ?? 'http://localhost:3000')
.split(',')
.map(origin => origin.trim())
.filter(Boolean);

app.enableCors({
origin: corsOrigins,
methods: ['GET', 'HEAD', 'OPTIONS'],
});
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
await app.listen(process.env.PORT ?? 3000);

const config = new DocumentBuilder()
.setTitle('WorkSight')
.setDescription('Check your tasks, manage your well-being')
Expand All @@ -15,5 +26,9 @@ async function bootstrap() {
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);

await app.listen(port);
logger.log(`API listening on http://localhost:${port} (CORS: ${corsOrigins.join(', ')})`);
logger.log('Data is fixture-backed from @worksight/common — not Supabase.');
}
bootstrap();
9 changes: 8 additions & 1 deletion apps/web/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ NEXT_PUBLIC_IS_OFFLINE=false
# Server-side offline flag (for server components)
IS_OFFLINE=false

# MVP data source (#18): when true, web fetches Nest API instead of in-process fixtures
# /demo always hits the API regardless of this flag
NEXT_PUBLIC_USE_API=false
NEXT_PUBLIC_API_URL=http://localhost:3001

# App URL for metadata and OpenGraph
NEXT_PUBLIC_APP_URL=http://localhost:3000

Expand All @@ -55,7 +60,9 @@ NEXT_PUBLIC_ENABLE_ERROR_REPORTING="false"
NEXT_PUBLIC_ENABLE_PERFORMANCE_MONITORING="true"

# API Configuration
API_BASE_URL="http://localhost:3000/api"
# Nest API (fixture-backed @worksight/common). Web uses NEXT_PUBLIC_* below.
API_BASE_URL="http://localhost:3001"
NEXT_PUBLIC_API_URL="http://localhost:3001"
API_TIMEOUT="10000"

# Email Configuration (if needed)
Expand Down
8 changes: 6 additions & 2 deletions apps/web/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,16 @@ const nextConfig: NextConfig = {
},
};
}
const commonDist = path.resolve(__dirname, '../../packages/common/dist');
config.resolve.alias = {
...config.resolve.alias,
'@': path.resolve(__dirname, 'src'),
'@worksight/assets': path.resolve(__dirname, '../../packages/assets/dist'),
'@worksight/common': path.resolve(__dirname, '../../packages/common/dist')
}
'@worksight/common/data': path.resolve(commonDist, 'data'),
'@worksight/common/types': path.resolve(commonDist, 'types'),
'@worksight/common/utils': path.resolve(commonDist, 'utils'),
'@worksight/common': commonDist,
};
return config;
},

Expand Down
96 changes: 8 additions & 88 deletions apps/web/src/app/admin/surveys/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,103 +41,23 @@ import {
} from 'lucide-react';
import Link from 'next/link';
import { useEffect, useMemo, useState } from 'react';

interface Survey {
id: string;
title: string;
description: string;
status: 'draft' | 'active' | 'paused' | 'completed';
questionCount: number;
responseCount: number;
createdAt: string;
lastModified: string;
createdBy: string;
category: 'burnout' | 'satisfaction' | 'wellness' | 'feedback';
targetAudience: 'all' | 'managers' | 'employees' | 'specific';
}

const mockSurveys: Survey[] = [
{
id: '1',
title: 'Burnout Assessment 2025',
description: 'Comprehensive burnout evaluation for all employees',
status: 'active',
questionCount: 15,
responseCount: 247,
createdAt: '2025-01-15',
lastModified: '2025-01-20',
createdBy: 'Admin User',
category: 'burnout',
targetAudience: 'all',
},
{
id: '2',
title: 'Job Satisfaction Survey',
description: 'Quarterly job satisfaction and engagement survey',
status: 'active',
questionCount: 12,
responseCount: 156,
createdAt: '2025-01-10',
lastModified: '2025-01-18',
createdBy: 'HR Manager',
category: 'satisfaction',
targetAudience: 'employees',
},
{
id: '3',
title: 'Manager Feedback Survey',
description: 'Leadership effectiveness and team dynamics assessment',
status: 'draft',
questionCount: 8,
responseCount: 0,
createdAt: '2025-01-22',
lastModified: '2025-01-22',
createdBy: 'Admin User',
category: 'feedback',
targetAudience: 'managers',
},
{
id: '4',
title: 'Wellness Check Q4 2024',
description: 'Mental health and wellness assessment',
status: 'completed',
questionCount: 10,
responseCount: 312,
createdAt: '2024-10-01',
lastModified: '2024-12-31',
createdBy: 'Wellness Team',
category: 'wellness',
targetAudience: 'all',
},
{
id: '5',
title: 'Remote Work Experience',
description: 'Evaluation of remote work setup and productivity',
status: 'paused',
questionCount: 14,
responseCount: 89,
createdAt: '2025-01-05',
lastModified: '2025-01-19',
createdBy: 'Operations Lead',
category: 'feedback',
targetAudience: 'all',
},
];
import { getMvpSurveys, type MvpSurvey } from '@/lib/mvp-data';

function SurveyManagementContent() {
const { logout } = useAuth();
const [surveys, setSurveys] = useState<Survey[]>([]);
const [surveys, setSurveys] = useState<MvpSurvey[]>([]);
const [searchTerm, setSearchTerm] = useState('');
const [statusFilter, setStatusFilter] = useState<string>('all');
const [categoryFilter, setCategoryFilter] = useState<string>('all');
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
// Simulate API call
setTimeout(() => {
setSurveys(mockSurveys);
setIsLoading(false);
}, 1000);
const fixtureSurveys = getMvpSurveys();
if (fixtureSurveys.length === 0) {
throw new Error('Common survey fixtures empty; refusing silent empty fallback');
}
setSurveys(fixtureSurveys);
setIsLoading(false);
}, []);

const handleLogout = async () => {
Expand Down
Loading
Loading