import cursor files
This commit is contained in:
171
team/index.html
Normal file
171
team/index.html
Normal file
@@ -0,0 +1,171 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Teams · Agile Maturity</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<style>
|
||||
:root{--bg:#0b0d10;--card:#12161b;--text:#e6edf3;--muted:#9da7b3;--brand:#5bb8ff}
|
||||
*{box-sizing:border-box}
|
||||
body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif;background:var(--bg);color:var(--text)}
|
||||
.container{max-width:960px;margin:0 auto;padding:20px}
|
||||
a{color:var(--brand)}
|
||||
.card{background:var(--card);border:1px solid #222831;border-radius:12px;padding:20px}
|
||||
input[type="text"],input[type="file"]{background:#0d1117;border:1px solid #1f2630;border-radius:8px;padding:10px;color:var(--text);width:100%}
|
||||
button{background:var(--brand);color:#00111f;border:0;border-radius:8px;padding:10px 14px;cursor:pointer;font-weight:600}
|
||||
button.secondary{background:#232b36;color:var(--text);border:1px solid #2c3644}
|
||||
.row{display:flex;gap:12px;flex-wrap:wrap}
|
||||
pre{background:#0d1117;border:1px solid #1f2630;border-radius:10px;padding:12px;overflow:auto}
|
||||
label{display:block;font-size:12px;color:var(--muted);margin-top:8px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<p><a href="../company/index.html">← Companies</a> · <a href="../index.html">Home</a></p>
|
||||
<h1>Teams</h1>
|
||||
<section class="card">
|
||||
<h3>Create or edit a team</h3>
|
||||
<div class="row">
|
||||
<input id="tName" type="text" placeholder="Team name">
|
||||
<input id="tCoach" type="text" placeholder="Coach (optional)">
|
||||
<button id="saveTeam">Save</button>
|
||||
<button class="secondary" id="resetForm">Reset</button>
|
||||
</div>
|
||||
<label>Company</label>
|
||||
<div class="row">
|
||||
<select id="companySelect"></select>
|
||||
<button class="secondary" id="goCompany">Open company</button>
|
||||
</div>
|
||||
<label>Teams for selected company</label>
|
||||
<div id="list"></div>
|
||||
<div class="row" style="margin-top:12px">
|
||||
<button class="secondary" id="exportBtn">Export</button>
|
||||
<input id="importFile" type="file" accept="application/json">
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<script>
|
||||
const teamKey = 'teams';
|
||||
let editId = null;
|
||||
|
||||
function loadCompanies(){ try{ return JSON.parse(localStorage.getItem('companies')||'[]'); }catch{ return []; } }
|
||||
function loadTeams(){ try{ return JSON.parse(localStorage.getItem(teamKey)||'[]'); }catch{ return []; } }
|
||||
function saveTeams(list){ localStorage.setItem(teamKey, JSON.stringify(list)); }
|
||||
function uuid(){ return (crypto && crypto.randomUUID) ? crypto.randomUUID() : 'id-'+Math.random().toString(36).slice(2); }
|
||||
|
||||
function initCompanySelect(){
|
||||
const companies = loadCompanies();
|
||||
const sel = document.getElementById('companySelect');
|
||||
sel.innerHTML = '';
|
||||
companies.forEach(c=>{
|
||||
const opt = document.createElement('option');
|
||||
opt.value = c.id; opt.textContent = c.name + (c.domain? ' · '+c.domain:'');
|
||||
sel.appendChild(opt);
|
||||
});
|
||||
const params = new URLSearchParams(location.search);
|
||||
const cid = params.get('companyId');
|
||||
if(cid){ sel.value = cid; }
|
||||
sel.addEventListener('change', render);
|
||||
document.getElementById('goCompany').onclick = ()=>{
|
||||
const id = sel.value; if(id) location.href = `../company/index.html#${encodeURIComponent(id)}`;
|
||||
}
|
||||
}
|
||||
function render(){
|
||||
const cid = document.getElementById('companySelect').value;
|
||||
const list = document.getElementById('list');
|
||||
const teams = loadTeams().filter(t=>t.companyId===cid);
|
||||
if(teams.length===0){ list.innerHTML = '<p class="small">No teams for this company.</p>'; return; }
|
||||
list.innerHTML = '';
|
||||
teams.forEach(t=>{
|
||||
const row = document.createElement('div');
|
||||
row.className = 'row';
|
||||
row.style.alignItems = 'center';
|
||||
row.style.justifyContent = 'space-between';
|
||||
const info = document.createElement('div');
|
||||
info.textContent = `${t.name}${t.coach? ' · Coach: '+t.coach:''}`;
|
||||
const actions = document.createElement('div');
|
||||
actions.className = 'row';
|
||||
const btnAssess = document.createElement('button');
|
||||
btnAssess.className = 'secondary';
|
||||
btnAssess.textContent = 'Assessments';
|
||||
btnAssess.onclick = ()=>{ location.href = `../assessments/index.html?companyId=${encodeURIComponent(t.companyId)}&teamId=${encodeURIComponent(t.id)}` };
|
||||
const btnEdit = document.createElement('button');
|
||||
btnEdit.className = 'secondary';
|
||||
btnEdit.textContent = 'Edit';
|
||||
btnEdit.onclick = ()=>{
|
||||
editId = t.id;
|
||||
document.getElementById('tName').value = t.name || '';
|
||||
document.getElementById('tCoach').value = t.coach || '';
|
||||
};
|
||||
const btnDel = document.createElement('button');
|
||||
btnDel.textContent = 'Delete';
|
||||
btnDel.style.background = '#ff6666';
|
||||
btnDel.onclick = ()=>{
|
||||
if(!confirm('Delete team and its assessments?')) return;
|
||||
const rest = loadTeams().filter(x=>x.id!==t.id);
|
||||
saveTeams(rest);
|
||||
const assessments = JSON.parse(localStorage.getItem('assessments')||'[]').filter(a=>a.teamId!==t.id);
|
||||
localStorage.setItem('assessments', JSON.stringify(assessments));
|
||||
if(editId===t.id) resetForm();
|
||||
render();
|
||||
};
|
||||
actions.append(btnAssess, btnEdit, btnDel);
|
||||
row.append(info, actions);
|
||||
list.appendChild(row);
|
||||
});
|
||||
}
|
||||
function resetForm(){ editId=null; document.getElementById('tName').value=''; document.getElementById('tCoach').value=''; }
|
||||
function onSave(){
|
||||
const name = document.getElementById('tName').value.trim();
|
||||
const coach = document.getElementById('tCoach').value.trim();
|
||||
const companyId = document.getElementById('companySelect').value;
|
||||
if(!companyId){ alert('Select a company'); return; }
|
||||
if(!name){ alert('Team name is required'); return; }
|
||||
const teams = loadTeams();
|
||||
if(editId){
|
||||
const idx = teams.findIndex(x=>x.id===editId);
|
||||
if(idx>=0){ teams[idx] = { ...teams[idx], name, coach }; }
|
||||
}else{
|
||||
teams.push({ id: uuid(), companyId, name, coach, createdAt: new Date().toISOString(), version: 1 });
|
||||
}
|
||||
saveTeams(teams);
|
||||
resetForm();
|
||||
render();
|
||||
}
|
||||
function onExport(){
|
||||
const cid = document.getElementById('companySelect').value;
|
||||
const data = loadTeams().filter(t=>t.companyId===cid);
|
||||
const blob = new Blob([JSON.stringify(data,null,2)], {type:'application/json'});
|
||||
const a = document.createElement('a');
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.download = `teams.${cid||'all'}.export.json`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(a.href);
|
||||
}
|
||||
function onImport(ev){
|
||||
const file = ev.target.files && ev.target.files[0];
|
||||
if(!file) return;
|
||||
file.text().then(text=>{
|
||||
try{
|
||||
const json = JSON.parse(text);
|
||||
if(!Array.isArray(json)) throw new Error('Expected an array');
|
||||
const existing = loadTeams();
|
||||
const merged = [...existing, ...json];
|
||||
saveTeams(merged);
|
||||
render();
|
||||
}catch(e){ alert('Invalid JSON: '+e.message); }
|
||||
});
|
||||
}
|
||||
document.getElementById('saveTeam').addEventListener('click', onSave);
|
||||
document.getElementById('resetForm').addEventListener('click', resetForm);
|
||||
document.getElementById('exportBtn').addEventListener('click', onExport);
|
||||
document.getElementById('importFile').addEventListener('change', onImport);
|
||||
initCompanySelect();
|
||||
render();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user