$pn){if(trim($pn)){$q=max(1,(int)($_POST['part_qty'][$i]??1));$pr=(float)str_replace(',','.',$_POST['part_price'][$i]??0);$parts[]=['n'=>trim($pn),'q'=>$q,'p'=>$pr];$tp+=$q*$pr;}}
$disc=min(100,max(0,(int)($_POST['discount']??0)));
$total=($tp+$man)*(1-$disc/100);
$nrM=trim($_POST['ticket_nr_manual']??'');
if(!$nrM)$nrM=$tid?($oldNr?:next_nr(TICKET_PREFIX,'tickets')):next_nr(TICKET_PREFIX,'tickets');
if(!$tid&&nr_exists($nrM,'tickets'))$nrM=next_nr(TICKET_PREFIX,'tickets');
if($tid&&$nrM!==$oldNr&&nr_exists($nrM,'tickets',$tid))$nrM=$oldNr;
$cUsername=null;$cPassword=null;
if($cid&&!$tid){$cl=db_one("SELECT * FROM clients WHERE id=?",[$cid]);if($cl){$cUsername=generate_username($cl['name']);$cPassword=generate_password(8);}}
$data=[p('device_tip'),p('device_brand'),p('device_model'),p('device_serial'),p('device_os'),$devPwd,p('problema'),p('diagnostic'),p('rezolutie'),$man,$disc,$total,p('garantie'),p('observatii'),$status,$_POST['priority']??'normal',$cid,$techId,$due,$nrM,$cUsername,$cPassword];
if($tid){
db_ex("UPDATE tickets SET device_tip=?,device_brand=?,device_model=?,device_serial=?,device_os=?,device_password=?,problema=?,diagnostic=?,rezolutie=?,manopera=?,discount=?,total=?,garantie=?,observatii=?,status=?,priority=?,client_id=?,tech_id=?,due_date=?,nr=? WHERE id=?",array_merge(array_slice($data,0,20),[$tid]));
db_ex("DELETE FROM ticket_parts WHERE ticket_id=?",[$tid]);
log_act('ticket_editat','crm',$nrM,'Tichet editat');
if($oldStatus!==$status)log_act('status_schimbat','crm',$nrM,"$oldStatus > $status");
}else{
$tid=db_ex("INSERT INTO tickets(device_tip,device_brand,device_model,device_serial,device_os,device_password,problema,diagnostic,rezolutie,manopera,discount,total,garantie,observatii,status,priority,client_id,tech_id,due_date,nr,client_username,client_password)VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",$data);
log_act('ticket_creat','crm',$nrM,'Tichet creat');
}
foreach($parts as $pt)db_ex("INSERT INTO ticket_parts(ticket_id,name,quantity,price)VALUES(?,?,?,?)",[$tid,$pt['n'],$pt['q'],$pt['p']]);
if($status==='gata_livrare'&&$oldStatus!=='gata_livrare'&&$cid){$tk=db_one("SELECT * FROM tickets WHERE id=?",[$tid]);$cl=db_one("SELECT * FROM clients WHERE id=?",[$cid]);if($tk&&$cl)notify_ticket($tk,$cl,'gata_livrare');}
header("Location: index.php?p=ticket&id=$tid&ok=1");exit;
}
if($act==='del_ticket'){$tid=(int)$_POST['tid'];$t=db_one("SELECT nr FROM tickets WHERE id=?",[$tid]);db_ex("DELETE FROM tickets WHERE id=?",[$tid]);log_act('ticket_sters','crm',$t['nr']??$tid,'Tichet sters');header("Location: index.php?p=tickets&deleted=1");exit;}
if($act==='send_message'){$tid=(int)$_POST['ticket_id'];$msg=trim($_POST['message']??'');if($tid&&$msg){db_ex("INSERT INTO ticket_messages(ticket_id,sender,sender_role,message)VALUES(?,?,?,?)",[$tid,$user['name'],$user['role'],$msg]);log_act('mesaj_trimis','crm','T'.$tid,'Mesaj trimis');}header("Location: index.php?p=ticket&id=$tid#chat");exit;}
if($act==='save_client'){$cid=(int)($_POST['client_id']??0);$d=[p('name'),p('company'),p('email'),p('phone'),$_POST['type']??'pf',$_POST['rank']??'bronze',(int)($_POST['discount']??0),p('address'),p('cui'),p('notes')];if($cid){db_ex("UPDATE clients SET name=?,company=?,email=?,phone=?,type=?,`rank`=?,`discount`=?,address=?,cui=?,notes=? WHERE id=?",array_merge($d,[$cid]));log_act('client_editat','crm',p('name'),'Client editat');}else{db_ex("INSERT INTO clients(name,company,email,phone,type,`rank`,`discount`,address,cui,notes)VALUES(?,?,?,?,?,?,?,?,?,?)",$d);log_act('client_creat','crm',p('name'),'Client nou');}header("Location: index.php?p=clients&ok=1");exit;}
if($act==='del_client'){$cid=(int)$_POST['cid'];$c=db_one("SELECT name FROM clients WHERE id=?",[$cid]);db_ex("DELETE FROM clients WHERE id=?",[$cid]);log_act('client_sters','crm',$c['name']??$cid,'Client sters');header("Location: index.php?p=clients&deleted=1");exit;}
if($act==='save_programare'){$pid=(int)($_POST['pgr_id']??0);$nr=$pid?(db_one("SELECT nr FROM programari WHERE id=?",[$pid])['nr']??next_nr(PROGRAMARE_PREFIX,'programari')):next_nr(PROGRAMARE_PREFIX,'programari');$cid=pint('client_id')?:null;$d=[p('name'),p('phone'),p('email'),p('address'),p('problem'),$_POST['zi']??null,$_POST['interval_orar']??'',p('notes'),$_POST['status']??'nou',$_POST['tech_id']??null,$cid,$nr];if($pid){db_ex("UPDATE programari SET name=?,phone=?,email=?,address=?,problem=?,zi=?,interval_orar=?,notes=?,status=?,tech_id=?,client_id=? WHERE id=?",array_merge(array_slice($d,0,11),[$pid]));log_act('pgr_editat','pgr',$nr,'Programare editata');}else{db_ex("INSERT INTO programari(name,phone,email,address,problem,zi,interval_orar,notes,status,tech_id,client_id,nr)VALUES(?,?,?,?,?,?,?,?,?,?,?,?)",$d);log_act('pgr_creat','pgr',$nr,'Programare noua');}header("Location: index.php?p=programari&ok=1");exit;}
if($act==='del_programare'){$pid=(int)$_POST['pid'];$pg=db_one("SELECT nr FROM programari WHERE id=?",[$pid]);db_ex("DELETE FROM programari WHERE id=?",[$pid]);log_act('pgr_sters','pgr',$pg['nr']??$pid,'Programare stearsa');header("Location: index.php?p=programari&deleted=1");exit;}
if($act==='save_contract'){$ctid=(int)($_POST['ctr_id']??0);$ref=$ctid?(db_one("SELECT ref FROM contracte WHERE id=?",[$ctid])['ref']??next_nr(CONTRACT_PREFIX,'contracte','ref')):next_nr(CONTRACT_PREFIX,'contracte','ref');$cid=pint('client_id')?:null;$d=[p('firma'),p('cui'),p('contact_nume'),p('contact_telefon'),p('contact_email'),p('oras'),p('adresa'),$_POST['tip_contract']??'abonament',(int)($_POST['durata_luni']??12),$_POST['data_inceput']??date('Y-m-d'),$_POST['sla']??'8h',$_POST['mod_interventie']??'ambele',json_encode($_POST['servicii']??[]),json_encode($_POST['echipamente']??[]),pf('total_fix'),$_POST['status']??'nou',p('notes'),$cid,$ref];if($ctid){db_ex("UPDATE contracte SET firma=?,cui=?,contact_nume=?,contact_telefon=?,contact_email=?,oras=?,adresa=?,tip_contract=?,durata_luni=?,data_inceput=?,sla=?,mod_interventie=?,servicii=?,echipamente=?,total_fix=?,status=?,notes=?,client_id=? WHERE id=?",array_merge(array_slice($d,0,18),[$ctid]));log_act('ctr_editat','ctr',$ref,'Contract editat');}else{db_ex("INSERT INTO contracte(firma,cui,contact_nume,contact_telefon,contact_email,oras,adresa,tip_contract,durata_luni,data_inceput,sla,mod_interventie,servicii,echipamente,total_fix,status,notes,client_id,ref)VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",$d);log_act('ctr_creat','ctr',$ref,'Contract nou');}header("Location: index.php?p=contracte&ok=1");exit;}
if($act==='del_contract'){$ctid=(int)$_POST['ctid'];$ct=db_one("SELECT ref FROM contracte WHERE id=?",[$ctid]);db_ex("DELETE FROM contracte WHERE id=?",[$ctid]);log_act('ctr_sters','ctr',$ct['ref']??$ctid,'Contract sters');header("Location: index.php?p=contracte&deleted=1");exit;}
if($act==='save_print'){$prid=(int)($_POST['print_id']??0);$nr=$prid?(db_one("SELECT nr FROM print_orders WHERE id=?",[$prid])['nr']??next_nr(PRINT_PREFIX,'print_orders')):next_nr(PRINT_PREFIX,'print_orders');$cid=pint('client_id')?:null;$d=[p('client_name'),p('client_phone'),p('client_email'),p('tip_lucrare'),p('format'),(int)($_POST['cantitate']??1),$_POST['culori']??'color',(int)isset($_POST['fata_verso']),p('hartie'),(int)isset($_POST['laminare']),p('note'),pf('pret_estimat'),$_POST['status']??'nou',$cid,$nr];if($prid){db_ex("UPDATE print_orders SET client_name=?,client_phone=?,client_email=?,tip_lucrare=?,format=?,cantitate=?,culori=?,fata_verso=?,hartie=?,laminare=?,note=?,pret_estimat=?,status=?,client_id=? WHERE id=?",array_merge(array_slice($d,0,14),[$prid]));log_act('print_editat','print',$nr,'Comanda editata');}else{db_ex("INSERT INTO print_orders(client_name,client_phone,client_email,tip_lucrare,format,cantitate,culori,fata_verso,hartie,laminare,note,pret_estimat,status,client_id,nr)VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",$d);log_act('print_creat','print',$nr,'Comanda print noua');if(p('client_phone'))send_sms(p('client_phone'),"HEL Print: Comanda $nr inregistrata. ".APP_URL);}header("Location: index.php?p=print&ok=1");exit;}
if($act==='del_print'){$prid=(int)$_POST['prid'];$pr=db_one("SELECT nr FROM print_orders WHERE id=?",[$prid]);db_ex("DELETE FROM print_orders WHERE id=?",[$prid]);log_act('print_sters','print',$pr['nr']??$prid,'Comanda stearsa');header("Location: index.php?p=print&deleted=1");exit;}
if($act==='save_user'&&is_admin()){$uid=(int)($_POST['user_id']??0);$active=(int)isset($_POST['active']);if($uid){db_ex("UPDATE users SET name=?,email=?,phone=?,role=?,active=? WHERE id=?",[p('name'),p('email'),p('phone'),$_POST['role']??'tehnician',$active,$uid]);}else{$plain=generate_password();$hash=password_hash($plain,PASSWORD_BCRYPT,['cost'=>12]);db_ex("INSERT INTO users(username,password,name,email,phone,role)VALUES(?,?,?,?,?,?)",[p('username'),$hash,p('name'),p('email'),p('phone'),$_POST['role']??'tehnician']);if(p('email'))notify_new_user(p('email'),p('name'),p('username'),$plain);$_SESSION['flash']="success|User creat! Parola: $plain";}log_act('user_editat','crm',p('username'),'User salvat');header("Location: index.php?p=users");exit;}
if($act==='del_user'&&is_admin()){$uid=(int)$_POST['uid'];if($uid===$user['id']){$_SESSION['flash']="danger|Nu poti sterge propriul cont.";}else{$u=db_one("SELECT username FROM users WHERE id=?",[$uid]);db_ex("DELETE FROM users WHERE id=?",[$uid]);log_act('user_sters','crm',$u['username']??$uid,'User sters');$_SESSION['flash']="success|Utilizatorul a fost sters.";}header("Location: index.php?p=users");exit;}
if($act==='toggle_active'&&is_admin()){$uid=(int)$_POST['uid'];if($uid!==$user['id']){$u=db_one("SELECT active,username FROM users WHERE id=?",[$uid]);$na=$u['active']?0:1;db_ex("UPDATE users SET active=? WHERE id=?",[$na,$uid]);$_SESSION['flash']='success|'.($na?'Activat.':'Dezactivat.');}header("Location: index.php?p=users");exit;}
if($act==='set_pwd_manual'){$uid=(int)$_POST['uid'];$np=$_POST['new_pwd_manual']??'';if(strlen($np)<6){$_SESSION['flash']="danger|Minim 6 caractere.";header("Location: index.php?p=users");exit;}$h=password_hash($np,PASSWORD_BCRYPT,['cost'=>12]);db_ex("UPDATE users SET password=? WHERE id=?",[$h,$uid]);$u=db_one("SELECT name,username FROM users WHERE id=?",[$uid]);log_act('parola_schimbata','crm',$u['username']??$uid,'Parola setata manual');$_SESSION['flash']="success|Parola setata pentru ".e($u['name']??'').".";header("Location: index.php?p=users");exit;}
if($act==='change_pwd'&&is_admin()){$uid=(int)$_POST['uid'];$plain=generate_password();$h=password_hash($plain,PASSWORD_BCRYPT,['cost'=>12]);db_ex("UPDATE users SET password=? WHERE id=?",[$h,$uid]);$u=db_one("SELECT * FROM users WHERE id=?",[$uid]);if($u['email'])notify_new_user($u['email'],$u['name'],$u['username'],$plain);$_SESSION['flash']="info|Parola resetata: $plain";header("Location: index.php?p=users");exit;}
if($act==='my_pwd'){$old=$_POST['old_pwd']??'';$new=$_POST['new_pwd']??'';$new2=$_POST['new_pwd2']??'';if(!password_verify($old,$user['password']))$_SESSION['flash']="danger|Parola curenta gresita.";elseif(strlen($new)<6)$_SESSION['flash']="danger|Minim 6 caractere.";elseif($new!==$new2)$_SESSION['flash']="danger|Parolele nu se potrivesc.";else{$h=password_hash($new,PASSWORD_BCRYPT,['cost'=>12]);db_ex("UPDATE users SET password=? WHERE id=?",[$h,$user['id']]);$_SESSION['user']['password']=$h;$user['password']=$h;log_act('parola_schimbata','crm',$user['username'],'Parola schimbata');$_SESSION['flash']="success|Parola schimbata!";}header("Location: index.php?p=profile");exit;}
}
}
if(isset($_SESSION['flash'])){[$ft,$fm]=explode('|',$_SESSION['flash'],2);$flash=flash($ft,$fm);unset($_SESSION['flash']);}
if(isset($_GET['ok']))$flash=flash('success','Salvat cu succes!');
if(isset($_GET['deleted']))$flash=flash('info','Sters.');
$p=$_GET['p']??'dashboard';
// API
if($p==='api'){header('Content-Type: application/json');$a=$_GET['a']??'';
if($a==='search'){$q=trim($_GET['q']??'');if(strlen($q)<2){echo json_encode(['results'=>[]]);exit;}$lq="%$q%";$res=[];
$tix=db_q("SELECT t.id,t.nr,t.status,t.device_brand,t.device_model,c.name cn FROM tickets t LEFT JOIN clients c ON c.id=t.client_id WHERE t.nr LIKE ? OR t.device_brand LIKE ? OR t.device_model LIKE ? OR c.name LIKE ? LIMIT 5",[$lq,$lq,$lq,$lq]);
foreach($tix as $t)$res[]=['id'=>$t['id'],'page'=>'ticket','icon'=>'🔧','title'=>$t['nr'].' — '.trim($t['device_brand'].' '.$t['device_model']),'sub'=>$t['cn']??'','module'=>'crm','module_label'=>'Service'];
$cls=db_q("SELECT id,name,company,phone FROM clients WHERE name LIKE ? OR company LIKE ? OR phone LIKE ? LIMIT 4",[$lq,$lq,$lq]);
foreach($cls as $c)$res[]=['id'=>$c['id'],'page'=>'client-form','icon'=>'👥','title'=>$c['name'].($c['company']?' ('.$c['company'].')':''),'sub'=>$c['phone']??'','module'=>'crm','module_label'=>'Client'];
$pgr=db_q("SELECT id,nr,name,phone FROM programari WHERE name LIKE ? OR phone LIKE ? LIMIT 3",[$lq,$lq]);
foreach($pgr as $pg)$res[]=['id'=>$pg['id'],'page'=>'programare','icon'=>'📅','title'=>$pg['nr'].' — '.$pg['name'],'sub'=>$pg['phone']??'','module'=>'pgr','module_label'=>'Programare'];
echo json_encode(['results'=>$res]);exit;}
if($a==='client_rank'){$cid=(int)($_GET['id']??0);$c=db_one("SELECT `rank`,`discount` FROM clients WHERE id=?",[$cid]);$rk=ranks()[$c['rank']??'bronze']??['label'=>'Bronze','discount'=>0];echo json_encode(['rank_label'=>$rk['label'],'discount'=>$c['discount']??$rk['discount']]);exit;}
echo json_encode(['error'=>'unknown']);exit;}
// Export
if($p==='export'){$type=$_GET['type']??'';
if($type==='tickets'){$rows=db_q("SELECT t.nr,c.name client,c.phone,t.device_tip,t.device_brand,t.device_model,t.device_serial,t.status,t.priority,t.problema,t.manopera,t.discount,t.total,t.created_at FROM tickets t LEFT JOIN clients c ON c.id=t.client_id ORDER BY t.created_at DESC");export_csv($rows,'tichete_'.date('Y-m-d'),['Nr','Client','Telefon','Tip','Brand','Model','Serie','Status','Prioritate','Problema','Manopera','Discount%','Total','Creat']);}
if($type==='clients'){$rows=db_q("SELECT name,company,type,`rank`,`discount`,phone,email,address,cui,created_at FROM clients ORDER BY name");export_csv($rows,'clienti_'.date('Y-m-d'),['Nume','Companie','Tip','Rang','Discount%','Telefon','Email','Adresa','CUI','Creat']);}
if($type==='programari'){$rows=db_q("SELECT nr,name,phone,email,address,problem,zi,interval_orar,status,created_at FROM programari ORDER BY created_at DESC");export_csv($rows,'programari_'.date('Y-m-d'),['Nr','Nume','Telefon','Email','Adresa','Problema','Zi','Interval','Status','Creat']);}
if($type==='contracte'){$rows=db_q("SELECT ref,firma,cui,contact_telefon,tip_contract,durata_luni,total_fix,status,created_at FROM contracte ORDER BY created_at DESC");export_csv($rows,'contracte_'.date('Y-m-d'),['Ref','Firma','CUI','Telefon','Tip','Luni','Total RON','Status','Creat']);}
header("Location: index.php?p=dashboard");exit;}
// Page data
$pd=[];
switch($p){
case 'dashboard':
$pd['t_active']=db_one("SELECT COUNT(*) c FROM tickets WHERE status NOT IN('finalizat','anulat')")['c']??0;
$pd['t_urgent']=db_one("SELECT COUNT(*) c FROM tickets WHERE priority IN('urgent','critic') AND status NOT IN('finalizat','anulat')")['c']??0;
$pd['t_ready']=db_one("SELECT COUNT(*) c FROM tickets WHERE status='gata_livrare'")['c']??0;
$pd['t_rev']=db_one("SELECT COALESCE(SUM(total),0) v FROM tickets WHERE status='finalizat' AND MONTH(created_at)=MONTH(NOW()) AND YEAR(created_at)=YEAR(NOW())")['v']??0;
$pd['pgr_nou']=db_one("SELECT COUNT(*) c FROM programari WHERE status='nou'")['c']??0;
$pd['ctr_activ']=db_one("SELECT COUNT(*) c FROM contracte WHERE status='activ'")['c']??0;
$pd['print_nou']=db_one("SELECT COUNT(*) c FROM print_orders WHERE status='nou'")['c']??0;
$pd['clients']=db_one("SELECT COUNT(*) c FROM clients")['c']??0;
$pd['st']=db_q("SELECT status,COUNT(*) c FROM tickets GROUP BY status");
$pd['recent']=db_q("SELECT t.*,c.name cn,u.name tn FROM tickets t LEFT JOIN clients c ON c.id=t.client_id LEFT JOIN users u ON u.id=t.tech_id ORDER BY t.created_at DESC LIMIT 6");
$pd['urgents']=db_q("SELECT t.*,c.name cn,c.phone FROM tickets t LEFT JOIN clients c ON c.id=t.client_id WHERE t.priority IN('urgent','critic') AND t.status NOT IN('finalizat','anulat') ORDER BY t.created_at DESC LIMIT 5");
$pd['pgr_today']=db_q("SELECT * FROM programari WHERE zi=CURDATE() AND status NOT IN('realizat','anulat') ORDER BY interval_orar");
$pd['devTypes']=db_q("SELECT device_tip tip,COUNT(*) c FROM tickets WHERE device_tip!='' GROUP BY device_tip ORDER BY c DESC LIMIT 8");
$pd['monthly']=db_q("SELECT DATE_FORMAT(created_at,'%b %Y') mon,DATE_FORMAT(created_at,'%Y-%m') ym,COUNT(*) c,COALESCE(SUM(CASE WHEN status='finalizat' THEN total ELSE 0 END),0) rev FROM tickets GROUP BY ym ORDER BY ym DESC LIMIT 6");
break;
case 'tickets':
$sq=$_GET['q']??'';$sf=$_GET['sf']??'';$st=$_GET['st']??'';$sp=$_GET['sp']??'';
$where=['1=1'];$wp=[];
if($sq){$where[]='(t.nr LIKE ? OR c.name LIKE ? OR t.device_brand LIKE ? OR t.device_model LIKE ? OR t.device_serial LIKE ? OR t.problema LIKE ?)';for($i=0;$i<6;$i++)$wp[]="%$sq%";}
if($sf){$where[]='t.status=?';$wp[]=$sf;}if($st){$where[]='t.device_tip=?';$wp[]=$st;}if($sp){$where[]='t.priority=?';$wp[]=$sp;}
$pd['tickets']=db_q("SELECT t.*,c.name cn,c.company,u.name tn FROM tickets t LEFT JOIN clients c ON c.id=t.client_id LEFT JOIN users u ON u.id=t.tech_id WHERE ".implode(' AND ',$where)." ORDER BY FIELD(t.priority,'critic','urgent','normal'),t.created_at DESC LIMIT 300",$wp);
$pd['counts']=db_q("SELECT status,COUNT(*) c FROM tickets GROUP BY status");
$pd['q']=$sq;$pd['sf']=$sf;$pd['st']=$st;$pd['sp']=$sp;break;
case 'ticket':
$tid=(int)($_GET['id']??0);
$pd['ticket']=db_one("SELECT t.*,c.name cn,c.email ce,c.phone cp,c.company cc,c.address ca,u.name tn FROM tickets t LEFT JOIN clients c ON c.id=t.client_id LEFT JOIN users u ON u.id=t.tech_id WHERE t.id=?",$tid?[$tid]:[0]);
$pd['parts']=$tid?db_q("SELECT * FROM ticket_parts WHERE ticket_id=?",[$tid]):[];
$pd['photos']=$tid?db_q("SELECT * FROM ticket_photos WHERE ticket_id=? ORDER BY uploaded_at",[$tid]):[];
$pd['messages']=$tid?db_q("SELECT * FROM ticket_messages WHERE ticket_id=? ORDER BY sent_at",[$tid]):[];
$pd['timeline']=$tid&&!empty($pd['ticket'])?db_q("SELECT * FROM activity_log WHERE target=? ORDER BY created_at ASC",[$pd['ticket']['nr']??'']):[];
break;
case 'ticket-form':
$tid=(int)($_GET['id']??0);
$pd['ticket']=$tid?db_one("SELECT * FROM tickets WHERE id=?",[$tid]):null;
$pd['parts']=$tid?db_q("SELECT * FROM ticket_parts WHERE ticket_id=?",[$tid]):[];
$pd['clients']=db_q("SELECT id,name,company FROM clients ORDER BY name");
$pd['techs']=db_q("SELECT id,name FROM users WHERE active=1 AND role IN('admin','tehnician') ORDER BY name");break;
case 'kanban':
$pd['cols']=[];foreach(array_keys(statuses()) as $s)$pd['cols'][$s]=db_q("SELECT t.*,c.name cn FROM tickets t LEFT JOIN clients c ON c.id=t.client_id WHERE t.status=? ORDER BY FIELD(t.priority,'critic','urgent','normal'),t.created_at DESC LIMIT 30",[$s]);break;
case 'clients':
$sq=trim($_GET['q']??'');$wp=[];$w='1=1';
if($sq){$w='(name LIKE ? OR company LIKE ? OR phone LIKE ? OR email LIKE ?)';for($i=0;$i<4;$i++)$wp[]="%$sq%";}
$pd['clients']=db_q("SELECT c.*,(SELECT COUNT(*) FROM tickets WHERE client_id=c.id) tt,(SELECT COUNT(*) FROM tickets WHERE client_id=c.id AND status NOT IN('finalizat','anulat')) at,(SELECT COALESCE(SUM(total),0) FROM tickets WHERE client_id=c.id AND status='finalizat') rev FROM clients c WHERE $w ORDER BY c.name",$wp);
$pd['q']=$sq;break;
case 'client-form':$cid=(int)($_GET['id']??0);$pd['client']=$cid?db_one("SELECT * FROM clients WHERE id=?",[$cid]):null;break;
case 'programari':
$sf=$_GET['sf']??'';$pd['pgr']=db_q("SELECT p.*,u.name tn FROM programari p LEFT JOIN users u ON u.id=p.tech_id".($sf?" WHERE p.status='$sf'":'')." ORDER BY COALESCE(p.zi,'9999-12-31'),p.created_at DESC LIMIT 200");
$pd['sf']=$sf;$pd['techs']=db_q("SELECT id,name FROM users WHERE active=1 AND role IN('admin','tehnician') ORDER BY name");$pd['clients']=db_q("SELECT id,name,company FROM clients ORDER BY name");break;
case 'programare':$pid=(int)($_GET['id']??0);$pd['pgr']=$pid?db_one("SELECT p.*,u.name tn FROM programari p LEFT JOIN users u ON u.id=p.tech_id WHERE p.id=?",[$pid]):null;break;
case 'contracte':$sf=$_GET['sf']??'';$pd['ctr']=db_q("SELECT * FROM contracte".($sf?" WHERE status='$sf'":'')." ORDER BY created_at DESC LIMIT 200");$pd['sf']=$sf;break;
case 'contract':$ctid=(int)($_GET['id']??0);$pd['ctr']=$ctid?db_one("SELECT * FROM contracte WHERE id=?",[$ctid]):null;break;
case 'contract-form':$ctid=(int)($_GET['id']??0);$pd['ctr']=$ctid?db_one("SELECT * FROM contracte WHERE id=?",[$ctid]):null;$pd['clients']=db_q("SELECT id,name,company FROM clients ORDER BY name");break;
case 'print':$sf=$_GET['sf']??'';$pd['orders']=db_q("SELECT * FROM print_orders".($sf?" WHERE status='$sf'":'')." ORDER BY created_at DESC LIMIT 200");$pd['sf']=$sf;$pd['clients']=db_q("SELECT id,name,company FROM clients ORDER BY name");break;
case 'analytics':
$pd['byStatus']=db_q("SELECT status,COUNT(*) c,COALESCE(SUM(total),0) rev FROM tickets GROUP BY status ORDER BY c DESC");
$pd['byDevice']=db_q("SELECT device_tip,COUNT(*) c FROM tickets WHERE device_tip!='' GROUP BY device_tip ORDER BY c DESC");
$pd['monthly']=db_q("SELECT DATE_FORMAT(created_at,'%b %Y') mon,COUNT(*) c,COALESCE(SUM(CASE WHEN status='finalizat' THEN total ELSE 0 END),0) rev FROM tickets GROUP BY DATE_FORMAT(created_at,'%Y-%m') ORDER BY DATE_FORMAT(created_at,'%Y-%m') LIMIT 12");
$pd['topClients']=db_q("SELECT c.name,c.company,COUNT(t.id) tot,COALESCE(SUM(t.total),0) rev FROM clients c LEFT JOIN tickets t ON t.client_id=c.id GROUP BY c.id HAVING tot>0 ORDER BY tot DESC LIMIT 10");
$pd['pgr_by_status']=db_q("SELECT status,COUNT(*) c FROM programari GROUP BY status");
$pd['ctr_by_status']=db_q("SELECT status,COUNT(*) c,COALESCE(SUM(total_fix),0) rev FROM contracte GROUP BY status");
$pd['print_by_status']=db_q("SELECT status,COUNT(*) c FROM print_orders GROUP BY status");
$all=db_q("SELECT problema,diagnostic,observatii FROM tickets");
$kw=['Imprimanta/Print'=>['imprimanta','toner','cartus','print','error 49'],'Nu Porneste'=>['nu porneste','bip','beep'],'Ecran/Display'=>['ecran','display','negru','monitor'],'Lent/Ingheata'=>['lent','incet','slow','ingheata'],'Virusi'=>['virus','malware','ransomware'],'HDD/SSD'=>['hdd','ssd','bad','sectoare'],'OS/Windows'=>['windows','linux','reinstal','crash','bsod'],'Retea/WiFi'=>['retea','wifi','internet'],'Baterie'=>['baterie','incarcator'],'RAM'=>['ram','memorie'],'Supraincalzire'=>['fierbinte','fan','ventilator']];
$kwc=[];foreach($kw as $l=>$ts){$c=0;foreach($all as $r){$tx=strtolower(($r['problema']??'').' '.($r['diagnostic']??'').' '.($r['observatii']??''));foreach($ts as $t){if(str_contains($tx,$t)){$c++;break;}}}if($c)$kwc[$l]=$c;}arsort($kwc);$pd['keywords']=$kwc;break;
case 'users':require_admin();$pd['users']=db_q("SELECT * FROM users WHERE role IN('admin','tehnician') ORDER BY role DESC,name");break;
case 'history':require_admin();$fu=$_GET['fu']??'';$fm=$_GET['fm']??'';$wp=[];$w='1=1';if($fu){$w.=' AND user_id=?';$wp[]=$fu;}if($fm){$w.=' AND module=?';$wp[]=$fm;}$pd['logs']=db_q("SELECT * FROM activity_log WHERE $w ORDER BY created_at DESC LIMIT 500",$wp);$pd['users']=db_q("SELECT id,name FROM users ORDER BY name");$pd['fu']=$fu;$pd['fm']=$fm;break;
case 'profile':break;
}
$urgentCount=db_one("SELECT COUNT(*) c FROM tickets WHERE priority IN('urgent','critic') AND status NOT IN('finalizat','anulat')")['c']??0;
$readyCount=db_one("SELECT COUNT(*) c FROM tickets WHERE status='gata_livrare'")['c']??0;
$pgrNouCount=db_one("SELECT COUNT(*) c FROM programari WHERE status='nou'")['c']??0;
$printNouCount=db_one("SELECT COUNT(*) c FROM print_orders WHERE status='nou'")['c']??0;
$totalNotif=$urgentCount+$readyCount+$pgrNouCount+$printNouCount;
$titles=['dashboard'=>'Dashboard','tickets'=>'Tichete Service','ticket'=>'Detalii Tichet','ticket-form'=>'Tichet Service','kanban'=>'Kanban Board','clients'=>'Clienti','client-form'=>'Client','programari'=>'Programari','programare'=>'Detalii Programare','contracte'=>'Contracte','contract'=>'Detalii Contract','contract-form'=>'Contract','print'=>'Print Shop','analytics'=>'Analiza & Statistici','users'=>'Utilizatori','history'=>'Istoric','profile'=>'Profil'];
?>
'.e($t['ce']).'':''],['Telefon',$t['cp']?''.e($t['cp']).'':''],['Adresa',e($t['ca']??'')],['Tehnician',e($t['tn']??'—')],['Termen',fmt_date($t['due_date'])]] as [$l,$v]):if($v&&$v!=='—'):?>
'#1e7fc8','ticket_editat'=>'#d97706','status_schimbat'=>'#6b48c8','mesaj_trimis'=>'#16a34a'];$tli=['ticket_creat'=>'🆕','ticket_editat'=>'✏️','status_schimbat'=>'🔄','mesaj_trimis'=>'💬'];
foreach($tl as $item):$col=$tlc[$item['action']]??'#94a3b8';$ico=$tli[$item['action']]??'📌';?>
=$ico?>
=fmt_dt($item['created_at'])?>
=e($item['detail']??'')?>
— =e($item['user_name']??'')?>
Tip
Rang
Nume / Companie
Telefon
Email
CUI
Tichete
Revenue
'PF','firma'=>'Firma','institutie'=>'Inst.'];foreach($d['clients'] as $c):?>