Mission Control - Tasks, Content, Calendar, Memory, Team, Office

This commit is contained in:
Neo
2026-02-18 21:32:53 +00:00
commit 1299db0840
7 changed files with 347 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
node_modules
.next
out
build
dist
*.log

10
app/globals.css Normal file
View File

@@ -0,0 +1,10 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background: #0f0f23;
color: white;
}

19
app/layout.tsx Normal file
View File

@@ -0,0 +1,19 @@
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "Mission Control - NodeCrew",
description: "Track tasks, content, calendar, memory, team, and office",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

263
app/page.tsx Normal file
View File

@@ -0,0 +1,263 @@
// Mission Control - Next.js App
// Track tasks, content, calendar, memory, team, and office
import { useState } from 'react';
// Types
type TaskStatus = 'todo' | 'in-progress' | 'done';
type Task = { id: string; title: string; status: TaskStatus; assignee: 'me' | 'jelena' | 'neo' };
type ContentStage = 'idea' | 'script' | 'thumbnail' | 'filming' | 'done';
type ContentItem = { id: string; title: string; stage: ContentStage; script?: string };
type CalendarEvent = { id: string; title: string; date: string; type: 'cron' | 'scheduled' };
type Memory = { id: string; title: string; date: string; preview: string };
type TeamMember = { id: string; name: string; role: string; status: 'working' | 'idle' };
export default function MissionControl() {
const [activeTab, setActiveTab] = useState('tasks');
return (
<div style={{ fontFamily: 'system-ui, sans-serif', minHeight: '100vh', background: '#0f0f23', color: 'white' }}>
{/* Header */}
<header style={{ padding: '20px 40px', borderBottom: '1px solid #1e1e3f', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<h1 style={{ fontSize: '1.8rem', fontWeight: 700 }}>🎯 Mission Control</h1>
<nav style={{ display: 'flex', gap: '10px' }}>
{['tasks', 'content', 'calendar', 'memory', 'team', 'office'].map(tab => (
<button
key={tab}
onClick={() => setActiveTab(tab)}
style={{
padding: '10px 20px',
background: activeTab === tab ? '#e94560' : 'transparent',
border: 'none',
borderRadius: '8px',
color: 'white',
cursor: 'pointer',
textTransform: 'capitalize'
}}
>
{tab}
</button>
))}
</nav>
</header>
{/* Content */}
<main style={{ padding: '40px' }}>
{activeTab === 'tasks' && <TasksBoard />}
{activeTab === 'content' && <ContentPipeline />}
{activeTab === 'calendar' && <Calendar />}
{activeTab === 'memory' && <Memory />}
{activeTab === 'team' && <Team />}
{activeTab === 'office' && <Office />}
</main>
</div>
);
}
// ============ TASKS BOARD ============
function TasksBoard() {
const [tasks, setTasks] = useState<Task[]>([
{ id: '1', title: 'Fix git backup push', status: 'in-progress', assignee: 'neo' },
{ id: '2', title: 'Deploy nodecrew landing page', status: 'done', assignee: 'neo' },
{ id: '3', title: 'Fix YouTube backup', status: 'todo', assignee: 'neo' },
{ id: '4', title: 'Setup Mission Control', status: 'in-progress', assignee: 'jelena' },
]);
const columns: { status: TaskStatus; label: string; color: string }[] = [
{ status: 'todo', label: 'To Do', color: '#6b7280' },
{ status: 'in-progress', label: 'In Progress', color: '#e94560' },
{ status: 'done', label: 'Done', color: '#10b981' },
];
return (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '20px' }}>
{columns.map(col => (
<div key={col.status} style={{ background: '#1a1a2e', borderRadius: '12px', padding: '20px' }}>
<h3 style={{ color: col.color, marginBottom: '20px' }}>{col.label}</h3>
{tasks.filter(t => t.status === col.status).map(task => (
<div key={task.id} style={{ background: '#16213e', padding: '15px', borderRadius: '8px', marginBottom: '10px' }}>
<p>{task.title}</p>
<span style={{ fontSize: '0.8rem', color: '#9ca3af' }}>@{task.assignee}</span>
</div>
))}
</div>
))}
</div>
);
}
// ============ CONTENT PIPELINE ============
function ContentPipeline() {
const [items, setItems] = useState<ContentItem[]>([
{ id: '1', title: 'ManoonOils Ad Copy', stage: 'script' },
{ id: '2', title: 'AI Agency Promo', stage: 'idea' },
{ id: '3', title: 'Product Launch Video', stage: 'thumbnail' },
]);
const stages: { stage: ContentStage; label: string }[] = [
{ stage: 'idea', label: '💡 Ideas' },
{ stage: 'script', label: '📝 Script' },
{ stage: 'thumbnail', label: '🖼️ Thumbnail' },
{ stage: 'filming', label: '🎬 Filming' },
{ stage: 'done', label: '✅ Done' },
];
return (
<div style={{ display: 'flex', gap: '15px', overflowX: 'auto', paddingBottom: '20px' }}>
{stages.map(s => (
<div key={s.stage} style={{ minWidth: '250px', background: '#1a1a2e', borderRadius: '12px', padding: '20px' }}>
<h3 style={{ marginBottom: '15px' }}>{s.label}</h3>
{items.filter(i => i.stage === s.stage).map(item => (
<div key={item.id} style={{ background: '#16213e', padding: '15px', borderRadius: '8px', marginBottom: '10px' }}>
{item.title}
</div>
))}
</div>
))}
</div>
);
}
// ============ CALENDAR ============
function Calendar() {
const events: CalendarEvent[] = [
{ id: '1', title: 'Twitter Briefing', date: '2026-02-19 06:00', type: 'cron' },
{ id: '2', title: 'Infra Status Report', date: '2026-02-19 07:00', type: 'cron' },
{ id: '3', title: 'ManoonOils Analytics', date: '2026-02-19 08:00', type: 'cron' },
{ id: '4', title: 'YouTube Backup', date: '2026-02-18 21:00', type: 'cron' },
];
return (
<div style={{ background: '#1a1a2e', borderRadius: '12px', padding: '30px' }}>
<h2 style={{ marginBottom: '30px' }}>📅 Scheduled Tasks & Cron Jobs</h2>
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ borderBottom: '1px solid #2a2a4e' }}>
<th style={{ textAlign: 'left', padding: '15px', color: '#9ca3af' }}>Task</th>
<th style={{ textAlign: 'left', padding: '15px', color: '#9ca3af' }}>Date/Time</th>
<th style={{ textAlign: 'left', padding: '15px', color: '#9ca3af' }}>Type</th>
</tr>
</thead>
<tbody>
{events.map(event => (
<tr key={event.id} style={{ borderBottom: '1px solid #2a2a4e' }}>
<td style={{ padding: '15px' }}>{event.title}</td>
<td style={{ padding: '15px', color: '#9ca3af' }}>{event.date}</td>
<td style={{ padding: '15px' }}>
<span style={{
background: event.type === 'cron' ? '#e94560' : '#10b981',
padding: '4px 12px', borderRadius: '20px', fontSize: '0.8rem'
}}>
{event.type}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
// ============ MEMORY ============
function Memory() {
const [search, setSearch] = useState('');
const memories: Memory[] = [
{ id: '1', title: 'ManoonOils Product Formula', date: '2026-02-07', preview: 'Professional formulation for anti-aging serum...' },
{ id: '2', title: 'Backup System Setup', date: '2026-02-05', preview: 'Storage Box mounted at /mnt/storagebox...' },
{ id: '3', title: 'Neo Agent Created', date: '2026-02-03', preview: 'Neo as CTO - infrastructure agent...' },
];
const filtered = memories.filter(m => m.title.toLowerCase().includes(search.toLowerCase()));
return (
<div>
<input
type="text"
placeholder="Search memories..."
value={search}
onChange={(e) => setSearch(e.target.value)}
style={{
width: '100%', padding: '15px', borderRadius: '8px', border: 'none',
background: '#1a1a2e', color: 'white', marginBottom: '30px', fontSize: '1rem'
}}
/>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: '20px' }}>
{filtered.map(mem => (
<div key={mem.id} style={{ background: '#1a1a2e', borderRadius: '12px', padding: '20px' }}>
<h3>{mem.title}</h3>
<p style={{ color: '#9ca3af', fontSize: '0.9rem', marginTop: '10px' }}>{mem.preview}</p>
<span style={{ color: '#6b7280', fontSize: '0.8rem' }}>{mem.date}</span>
</div>
))}
</div>
</div>
);
}
// ============ TEAM ============
function Team() {
const members: TeamMember[] = [
{ id: '1', name: 'Jelena', role: 'Chief of Staff', status: 'working' },
{ id: '2', name: 'Neo', role: 'CTO / DevOps', status: 'working' },
{ id: '3', name: 'Agent 3', role: 'Sales Agent', status: 'idle' },
{ id: '4', name: 'Agent 4', role: 'Ad Manager', status: 'idle' },
];
return (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))', gap: '20px' }}>
{members.map(member => (
<div key={member.id} style={{ background: '#1a1a2e', borderRadius: '12px', padding: '25px', display: 'flex', alignItems: 'center', gap: '15px' }}>
<div style={{
width: '50px', height: '50px', borderRadius: '50%',
background: member.status === 'working' ? '#10b981' : '#6b7280',
display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '1.5rem'
}}>
{member.name[0]}
</div>
<div>
<h3>{member.name}</h3>
<p style={{ color: '#9ca3af', fontSize: '0.9rem' }}>{member.role}</p>
<span style={{ color: member.status === 'working' ? '#10b981' : '#6b7280', fontSize: '0.8rem' }}>
{member.status === 'working' ? '● Working' : '○ Idle'}
</span>
</div>
</div>
))}
</div>
);
}
// ============ OFFICE ============
function Office() {
const agents = [
{ name: 'Jelena', area: 'Executive Suite', working: true, task: 'Managing operations' },
{ name: 'Neo', area: 'Server Room', working: true, task: 'Infrastructure monitoring' },
];
return (
<div style={{ background: '#1a1a2e', borderRadius: '12px', padding: '30px' }}>
<h2 style={{ marginBottom: '30px' }}>🏢 Digital Office</h2>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '20px' }}>
{agents.map(agent => (
<div key={agent.name} style={{ background: '#16213e', borderRadius: '12px', padding: '25px' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<h3>{agent.name}</h3>
<span style={{
width: '12px', height: '12px', borderRadius: '50%',
background: agent.working ? '#10b981' : '#6b7280'
}} />
</div>
<p style={{ color: '#9ca3af', marginTop: '10px' }}>📍 {agent.area}</p>
<p style={{ color: '#e94560', marginTop: '5px' }}>💻 {agent.task}</p>
</div>
))}
</div>
</div>
);
}

7
next.config.ts Normal file
View File

@@ -0,0 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: 'standalone',
};
export default nextConfig;

22
package.json Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "mission-control",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "14.2.35",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"typescript": "^5"
}
}

20
tsconfig.json Normal file
View File

@@ -0,0 +1,20 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": { "@/*": ["./*"] }
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}