diff --git a/webapp/README.md b/webapp/README.md new file mode 100644 index 0000000..14d5c49 --- /dev/null +++ b/webapp/README.md @@ -0,0 +1,255 @@ +# Team Project Tracker + +A modern, intuitive web application for tracking team projects, tasks, milestones, and project health status. + +## Features + +### Dashboard Overview +- **Quick Stats**: Visual summary of all projects with color-coded status indicators + - 🟢 On Track (green) - Projects progressing well + - 🟡 At Risk (yellow) - Projects with potential issues + - 🔴 Blocked (red) - Projects that need immediate attention + - 🟣 Completed (purple) - Finished projects +- **Project Cards**: Grid view of all projects with progress indicators +- **Real-time Updates**: Dashboard updates automatically as you make changes + +### Project Management +- **Create Projects**: Define project name, description, owner, dates, and status +- **Edit Projects**: Update project details at any time +- **Delete Projects**: Remove projects when no longer needed +- **Project Details**: Comprehensive view of each project including: + - Project metadata (owner, dates, status) + - Task list with completion tracking + - Milestone tracking with achievement status + +### Task Management +- **Add Tasks**: Create tasks with: + - Name and description + - Status (To Do, In Progress, Completed, Blocked) + - Assignee + - Due date +- **Edit Tasks**: Update task details as work progresses +- **Delete Tasks**: Remove completed or cancelled tasks +- **Visual Indicators**: Color-coded borders show task status at a glance + +### Milestone Tracking +- **Define Milestones**: Set key project milestones with: + - Name and description + - Target date + - Status (Pending, Achieved, Missed) +- **Track Progress**: Monitor milestone achievement +- **Visual Status**: Clear indicators for milestone completion + +### Data Persistence +- **Local Storage**: All data is automatically saved to your browser +- **No Backend Required**: Works completely offline +- **Sample Data**: Includes example projects to get you started + +## Getting Started + +### Quick Start +1. Open `index.html` in your web browser +2. The app loads with sample projects to demonstrate features +3. Start creating your own projects by clicking "+ New Project" + +### Usage + +#### Creating a New Project +1. Click the "+ New Project" button in the header +2. Fill in the project details: + - **Project Name** (required) + - **Description** (optional) + - **Status** (required) - Select current health status + - **Project Owner** (optional) + - **Start Date** (optional) + - **Target End Date** (optional) +3. Click "Save Project" + +#### Managing Tasks +1. Click on a project card to view details +2. In the Tasks section, click "+ Add Task" +3. Fill in task details and save +4. Edit or delete tasks using the action buttons +5. Change task status to track progress + +#### Setting Milestones +1. From the project detail view, go to the Milestones section +2. Click "+ Add Milestone" +3. Set the milestone name, date, and status +4. Track achievement as you progress + +#### Understanding Project Status + +**On Track (Green)** +- Project is progressing as planned +- No significant blockers +- Team is meeting deadlines + +**At Risk (Yellow)** +- Potential issues identified +- May miss deadlines without intervention +- Requires manager attention + +**Blocked (Red)** +- Critical blockers preventing progress +- Immediate action required +- Escalation needed + +**Completed (Purple)** +- Project successfully finished +- All tasks completed +- Archived for reference + +## Technical Details + +### Technology Stack +- **HTML5**: Semantic markup +- **CSS3**: Modern styling with CSS Grid and Flexbox +- **Vanilla JavaScript**: No frameworks, pure ES6+ +- **Local Storage API**: Browser-based data persistence + +### Browser Support +- Chrome/Edge (latest) +- Firefox (latest) +- Safari (latest) +- Any modern browser with ES6 support + +### File Structure +``` +webapp/ +├── index.html # Main HTML file +├── css/ +│ └── styles.css # All styling +├── js/ +│ └── app.js # Application logic +└── README.md # This file +``` + +### Data Model + +**Project Structure:** +```javascript +{ + id: "unique_id", + name: "Project Name", + description: "Project description", + status: "on-track|at-risk|blocked|completed", + owner: "Project Owner", + startDate: "YYYY-MM-DD", + endDate: "YYYY-MM-DD", + tasks: [...], + milestones: [...] +} +``` + +**Task Structure:** +```javascript +{ + id: "unique_id", + name: "Task Name", + description: "Task description", + status: "todo|in-progress|completed|blocked", + assignee: "Person Name", + dueDate: "YYYY-MM-DD" +} +``` + +**Milestone Structure:** +```javascript +{ + id: "unique_id", + name: "Milestone Name", + description: "Milestone description", + date: "YYYY-MM-DD", + status: "pending|achieved|missed" +} +``` + +## Features Highlights + +### Intuitive Interface +- Clean, modern design +- Color-coded status indicators +- Easy navigation between views +- Responsive layout for all screen sizes + +### Quick Overview +- Dashboard provides instant project health visibility +- Stats cards show at-a-glance metrics +- Progress bars on project cards +- Visual differentiation of project status + +### Risk Management +- Clear identification of at-risk projects +- Blocked project highlighting +- Task-level status tracking +- Milestone achievement monitoring + +## Tips for Best Use + +1. **Update Status Regularly**: Keep project status current for accurate overview +2. **Use Descriptions**: Add context to help team members understand work +3. **Set Realistic Dates**: Target dates help track progress +4. **Assign Tasks**: Clear ownership improves accountability +5. **Track Milestones**: Break projects into measurable achievements +6. **Review Dashboard**: Regular checks help identify risks early + +## Data Management + +### Exporting Data +Your data is stored in browser Local Storage. To backup: +1. Open browser Developer Tools (F12) +2. Go to Application > Local Storage +3. Find key: `projectTrackerData` +4. Copy the JSON value + +### Importing Data +To restore or import data: +1. Open browser Developer Tools (F12) +2. Go to Application > Local Storage +3. Set key `projectTrackerData` with your JSON data +4. Refresh the page + +### Clearing Data +To start fresh: +1. Open browser Developer Tools (F12) +2. Go to Application > Local Storage +3. Delete key: `projectTrackerData` +4. Refresh the page + +## Customization + +The app uses CSS variables for easy theming. Edit `css/styles.css`: + +```css +:root { + --primary-color: #4f46e5; /* Main accent color */ + --on-track: #10b981; /* Success/on-track color */ + --at-risk: #f59e0b; /* Warning/at-risk color */ + --blocked: #ef4444; /* Error/blocked color */ + /* ... more variables */ +} +``` + +## Future Enhancements + +Possible additions: +- Export to PDF/Excel +- Team member management +- Email notifications +- Calendar integration +- File attachments +- Comments and activity log +- Backend API integration +- User authentication +- Gantt chart view +- Time tracking + +## Support + +For issues or questions about the Turn.js library, visit: +- [Turn.js GitHub Repository](https://github.com/blasten/turn.js) + +## License + +This webapp is part of the Turn.js project. See the main repository for license information. diff --git a/webapp/css/styles.css b/webapp/css/styles.css new file mode 100644 index 0000000..fa28d95 --- /dev/null +++ b/webapp/css/styles.css @@ -0,0 +1,754 @@ +/* ==================== */ +/* CSS Variables */ +/* ==================== */ +:root { + --primary-color: #4f46e5; + --primary-hover: #4338ca; + --secondary-color: #64748b; + --danger-color: #ef4444; + --success-color: #10b981; + --warning-color: #f59e0b; + --blocked-color: #dc2626; + + --on-track: #10b981; + --at-risk: #f59e0b; + --blocked: #ef4444; + --completed: #8b5cf6; + + --bg-primary: #ffffff; + --bg-secondary: #f8fafc; + --bg-tertiary: #f1f5f9; + --border-color: #e2e8f0; + --text-primary: #1e293b; + --text-secondary: #64748b; + + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1); + + --radius-sm: 6px; + --radius-md: 8px; + --radius-lg: 12px; +} + +/* ==================== */ +/* Reset & Base Styles */ +/* ==================== */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif; + background: var(--bg-secondary); + color: var(--text-primary); + line-height: 1.6; +} + +/* ==================== */ +/* Layout */ +/* ==================== */ +.app-container { + min-height: 100vh; + display: flex; + flex-direction: column; +} + +.app-header { + background: var(--bg-primary); + border-bottom: 1px solid var(--border-color); + box-shadow: var(--shadow-sm); + position: sticky; + top: 0; + z-index: 100; +} + +.header-content { + max-width: 1400px; + margin: 0 auto; + padding: 1.5rem 2rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.header-content h1 { + font-size: 1.75rem; + font-weight: 700; + color: var(--text-primary); +} + +.main-content { + flex: 1; + max-width: 1400px; + width: 100%; + margin: 0 auto; + padding: 2rem; +} + +/* ==================== */ +/* Views */ +/* ==================== */ +.view { + display: none; +} + +.view.active { + display: block; +} + +/* ==================== */ +/* Buttons */ +/* ==================== */ +.btn { + padding: 0.625rem 1.25rem; + border: none; + border-radius: var(--radius-md); + font-size: 0.875rem; + font-weight: 600; + cursor: pointer; + transition: all 0.2s; + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.btn-primary { + background: var(--primary-color); + color: white; +} + +.btn-primary:hover { + background: var(--primary-hover); + transform: translateY(-1px); + box-shadow: var(--shadow-md); +} + +.btn-secondary { + background: var(--bg-tertiary); + color: var(--text-primary); +} + +.btn-secondary:hover { + background: var(--border-color); +} + +.btn-danger { + background: var(--danger-color); + color: white; +} + +.btn-danger:hover { + background: #dc2626; +} + +.btn-small { + padding: 0.375rem 0.75rem; + font-size: 0.75rem; +} + +/* ==================== */ +/* Dashboard */ +/* ==================== */ +.dashboard-header { + margin-bottom: 2rem; +} + +.dashboard-header h2 { + font-size: 1.875rem; + margin-bottom: 1.5rem; + color: var(--text-primary); +} + +.stats-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1.5rem; + margin-bottom: 2rem; +} + +.stat-card { + background: var(--bg-primary); + padding: 1.5rem; + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + border-left: 4px solid; + transition: transform 0.2s; +} + +.stat-card:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-lg); +} + +.stat-card.on-track { + border-color: var(--on-track); +} + +.stat-card.at-risk { + border-color: var(--at-risk); +} + +.stat-card.blocked { + border-color: var(--blocked); +} + +.stat-card.total { + border-color: var(--primary-color); +} + +.stat-value { + font-size: 2.5rem; + font-weight: 700; + margin-bottom: 0.25rem; +} + +.stat-card.on-track .stat-value { + color: var(--on-track); +} + +.stat-card.at-risk .stat-value { + color: var(--at-risk); +} + +.stat-card.blocked .stat-value { + color: var(--blocked); +} + +.stat-card.total .stat-value { + color: var(--primary-color); +} + +.stat-label { + font-size: 0.875rem; + color: var(--text-secondary); + font-weight: 500; +} + +/* ==================== */ +/* Projects Grid */ +/* ==================== */ +.projects-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); + gap: 1.5rem; +} + +.project-card { + background: var(--bg-primary); + border-radius: var(--radius-lg); + padding: 1.5rem; + box-shadow: var(--shadow-md); + cursor: pointer; + transition: all 0.2s; + border-top: 4px solid; +} + +.project-card:hover { + transform: translateY(-4px); + box-shadow: var(--shadow-lg); +} + +.project-card.on-track { + border-color: var(--on-track); +} + +.project-card.at-risk { + border-color: var(--at-risk); +} + +.project-card.blocked { + border-color: var(--blocked); +} + +.project-card.completed { + border-color: var(--completed); + opacity: 0.85; +} + +.project-card-header { + display: flex; + justify-content: space-between; + align-items: start; + margin-bottom: 1rem; +} + +.project-card-title { + font-size: 1.25rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.25rem; +} + +.project-status-badge { + padding: 0.25rem 0.75rem; + border-radius: 999px; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; +} + +.status-on-track { + background: rgba(16, 185, 129, 0.1); + color: var(--on-track); +} + +.status-at-risk { + background: rgba(245, 158, 11, 0.1); + color: var(--at-risk); +} + +.status-blocked { + background: rgba(239, 68, 68, 0.1); + color: var(--blocked); +} + +.status-completed { + background: rgba(139, 92, 246, 0.1); + color: var(--completed); +} + +.project-card-description { + color: var(--text-secondary); + font-size: 0.875rem; + margin-bottom: 1rem; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.project-card-meta { + display: flex; + gap: 1.5rem; + margin-top: 1rem; + padding-top: 1rem; + border-top: 1px solid var(--border-color); + font-size: 0.875rem; + color: var(--text-secondary); +} + +.project-card-meta-item { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.project-card-footer { + margin-top: 1rem; + padding-top: 1rem; + border-top: 1px solid var(--border-color); +} + +.project-progress { + display: flex; + justify-content: space-between; + font-size: 0.75rem; + margin-bottom: 0.5rem; + color: var(--text-secondary); +} + +.progress-bar { + height: 6px; + background: var(--bg-tertiary); + border-radius: 999px; + overflow: hidden; +} + +.progress-fill { + height: 100%; + background: var(--primary-color); + transition: width 0.3s; +} + +.project-card.on-track .progress-fill { + background: var(--on-track); +} + +.project-card.at-risk .progress-fill { + background: var(--at-risk); +} + +.project-card.blocked .progress-fill { + background: var(--blocked); +} + +/* ==================== */ +/* Project Detail View */ +/* ==================== */ +.detail-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2rem; +} + +.detail-actions { + display: flex; + gap: 1rem; +} + +.project-detail-header { + background: var(--bg-primary); + padding: 2rem; + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + margin-bottom: 2rem; +} + +.project-detail-title { + font-size: 2rem; + font-weight: 700; + margin-bottom: 0.5rem; +} + +.project-detail-meta { + display: flex; + flex-wrap: wrap; + gap: 2rem; + margin-top: 1.5rem; + font-size: 0.875rem; +} + +.meta-item { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.meta-label { + color: var(--text-secondary); + font-weight: 500; +} + +.meta-value { + color: var(--text-primary); + font-weight: 600; +} + +.project-sections { + display: grid; + gap: 2rem; +} + +.section { + background: var(--bg-primary); + padding: 2rem; + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; +} + +.section-title { + font-size: 1.25rem; + font-weight: 600; +} + +.empty-state { + text-align: center; + padding: 3rem 1rem; + color: var(--text-secondary); +} + +/* ==================== */ +/* Tasks */ +/* ==================== */ +.tasks-list { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.task-item { + padding: 1rem; + background: var(--bg-secondary); + border-radius: var(--radius-md); + border-left: 3px solid; + display: flex; + justify-content: space-between; + align-items: center; + transition: all 0.2s; +} + +.task-item:hover { + background: var(--bg-tertiary); +} + +.task-item.todo { + border-color: var(--secondary-color); +} + +.task-item.in-progress { + border-color: var(--primary-color); +} + +.task-item.completed { + border-color: var(--success-color); + opacity: 0.7; +} + +.task-item.blocked { + border-color: var(--danger-color); +} + +.task-content { + flex: 1; +} + +.task-name { + font-weight: 600; + margin-bottom: 0.25rem; +} + +.task-item.completed .task-name { + text-decoration: line-through; +} + +.task-meta { + display: flex; + gap: 1rem; + font-size: 0.75rem; + color: var(--text-secondary); +} + +.task-actions { + display: flex; + gap: 0.5rem; +} + +/* ==================== */ +/* Milestones */ +/* ==================== */ +.milestones-list { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.milestone-item { + padding: 1rem; + background: var(--bg-secondary); + border-radius: var(--radius-md); + border-left: 3px solid; + transition: all 0.2s; +} + +.milestone-item:hover { + background: var(--bg-tertiary); +} + +.milestone-item.pending { + border-color: var(--warning-color); +} + +.milestone-item.achieved { + border-color: var(--success-color); +} + +.milestone-item.missed { + border-color: var(--danger-color); +} + +.milestone-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.5rem; +} + +.milestone-name { + font-weight: 600; +} + +.milestone-date { + font-size: 0.875rem; + color: var(--text-secondary); +} + +.milestone-actions { + display: flex; + gap: 0.5rem; +} + +/* ==================== */ +/* Modal */ +/* ==================== */ +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 1000; + align-items: center; + justify-content: center; +} + +.modal.active { + display: flex; +} + +.modal-content { + background: var(--bg-primary); + border-radius: var(--radius-lg); + width: 90%; + max-width: 600px; + max-height: 90vh; + overflow-y: auto; + box-shadow: var(--shadow-lg); +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1.5rem; + border-bottom: 1px solid var(--border-color); +} + +.modal-header h3 { + font-size: 1.5rem; + font-weight: 600; +} + +.modal-close { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + color: var(--text-secondary); + padding: 0; + width: 2rem; + height: 2rem; + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-sm); + transition: all 0.2s; +} + +.modal-close:hover { + background: var(--bg-tertiary); + color: var(--text-primary); +} + +form { + padding: 1.5rem; +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; +} + +label { + display: block; + margin-bottom: 0.5rem; + font-weight: 500; + font-size: 0.875rem; + color: var(--text-primary); +} + +input[type="text"], +input[type="date"], +textarea, +select { + width: 100%; + padding: 0.625rem; + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + font-size: 0.875rem; + font-family: inherit; + transition: all 0.2s; +} + +input:focus, +textarea:focus, +select:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); +} + +textarea { + resize: vertical; +} + +.modal-actions { + display: flex; + justify-content: flex-end; + gap: 1rem; + padding-top: 1rem; + border-top: 1px solid var(--border-color); +} + +/* ==================== */ +/* Responsive */ +/* ==================== */ +@media (max-width: 768px) { + .header-content { + flex-direction: column; + gap: 1rem; + } + + .main-content { + padding: 1rem; + } + + .projects-grid { + grid-template-columns: 1fr; + } + + .stats-cards { + grid-template-columns: repeat(2, 1fr); + } + + .form-row { + grid-template-columns: 1fr; + } + + .detail-header { + flex-direction: column; + gap: 1rem; + align-items: stretch; + } + + .detail-actions { + flex-direction: column; + } +} + +/* ==================== */ +/* Utilities */ +/* ==================== */ +.empty-state { + text-align: center; + padding: 3rem 1rem; + color: var(--text-secondary); +} + +.empty-state-icon { + font-size: 3rem; + margin-bottom: 1rem; + opacity: 0.5; +} + +.empty-state-text { + font-size: 1rem; + margin-bottom: 1.5rem; +} diff --git a/webapp/index.html b/webapp/index.html new file mode 100644 index 0000000..774688c --- /dev/null +++ b/webapp/index.html @@ -0,0 +1,214 @@ + + +
+ + +${this.escapeHtml(project.description)}
+ ` : ''} + + +