$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']; ?> <?=APP_NAME?> · <?=$titles[$p]??'HUB'?>
+ Tichet📥 CSV + Client📥 CSV + Contract📥 CSV ✏️ Editeaza + Tichet Nou
Buna ziua, ! 👋
·
🔧
Tichete Active
⚠️ urgente
Gata Livrare
💰
RON
Revenue Luna Aceasta
📅
Programari Noi
📄
Contracte Active
🖨️
Comenzi Print Noi
👥
Clienti Totali
📊 Status Tichete
$s):$c=0;foreach($d['st'] as $r)if($r['status']===$k)$c=$r['c'];?>
🖥️ Top Echipamente
📅 Programari Azi —
·
🚨 Urgente/Critice
🕐 Tichete Recente
Nr.ClientEchipamentProblemaStatusTotal


0?''.fmt_money($t['total']).'':'—'?>
+ Tichet Nou
$cards):$s=$sts[$sk];$cnt=count($cards);?>
0?' · '.fmt_money($t['total']).'':''?>
Gol
Reset rezultate
Toate$s):$c=0;foreach($d['counts'] as $r)if($r['status']===$k)$c=$r['c'];?>;color:#fff;padding:0 5px;border-radius:8px;font-size:9px'>$c":'';?>
Nr.ClientEchipamentS/NProblemaTehnicianStatusPrior.Total

'.e($t['company']).'':''?>

0?''.fmt_money($t['total']).'':'—'?>
Niciun tichet. Creeaza →
Tichet negasit.
'; else:?>

·
✏️← Inapoi
🖥️ Echipament
Parola
••••••••
🔐 Acces Portal Client
User:
Parola:
↗ Deschide portal
👤 Client
'.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!=='—'):?>
🔧 Tehnic
0):?>
📦 Piese & Financiar
x
0):?>
Manopera
0):?>
Discount %
TOTAL
✅ Garantie:
📸 Poze Echipament
foto

Nicio poza.

💬 Mesaje / Chat
·

Niciun mesaj.

📅 Timeline
'#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']]??'📌';?>
📋 Informatii Generale
🖥️ Echipament
🔧 Tehnic
📦 Piese
DenumireCant.Pret RON
💰 Financiar
Anuleaza
Reset clienti
'PF','firma'=>'Firma','institutie'=>'Inst.'];foreach($d['clients'] as $c):?>
TipRangNume / CompanieTelefonEmailCUITicheteRevenue
'.e($c['company']).'':''?>
'.e($c['phone']).'':'—'?>'.e($c['email']).'':'—'?> / 0?''.fmt_money($c['rev']).'':'—'?>
✏️
Niciun client.
Anuleaza
Toate$s):?>
Nr.NumeTelefonAdresaZiIntervalProblemaTehnicianStatus
'.e($pg['phone']).'':'—'?>
Nicio programare.
Programare negasita.';else:?>

← Inapoi
👤 Client & Adresa
'.e($pg['phone']).'':''],['Email',$pg['email']?''.e($pg['email']).'':''],['Adresa',$pg['address']]] as [$l,$v]):if($v):?>
📋 Detalii & Status
Problema
Toate$s):?>
Ref.FirmaTelefonTipDurataTotal/lunaData StartStatus
'.e($ct['contact_telefon']).'':'—'?> luni0?''.fmt_money($ct['total_fix']).'':'—'?>
✏️
Niciun contract.
Contract negasit.';else:?>

✏️← Inapoi
🏢 Client & Contact
'.e($ct['contact_telefon']).'':''],['Email',$ct['contact_email']?''.e($ct['contact_email']).'':''],['Adresa',$ct['adresa']]] as [$l,$v]):if($v):?>
📄 Detalii Contract
Anuleaza
Toate$s):?>
Nr.ClientTelefonTip LucrareFormatCant.CuloriPret Est.Status

'.e($pr['client_phone']).'':'—'?>0?''.fmt_money($pr['pret_estimat']).'':'—'?>
Nicio comanda print.
🔍 Top Probleme Service
$cnt):$pct=round($cnt/$maxK*100);$col=$kc[$ki++%count($kc)];?>

Date insuficiente.

🖥️ Echipamente
📈 Revenue Lunar
📊 Service
StatusNr.Revenue
0?''.fmt_money($st['rev']).'':'—'?>
📅 Programari
StatusNr.
🤝 Contracte
StatusNr.Revenue
0?''.fmt_money($st['rev']).'':'—'?>
👥 Top Clienti
#ClientTicheteRevenue
'.e($tc['company']).'':''?>0?''.fmt_money($tc['rev']).'':'—'?>
UsernameNumeEmailRolStatusCreatUltima Auth.Actiuni
(tu)':''?>'.e($u['email']).'':'—'?>
'Login','logout'=>'Logout','ticket_creat'=>'Tichet Creat','ticket_editat'=>'Tichet Editat','ticket_sters'=>'Tichet Sters','status_schimbat'=>'Status Schimbat','mesaj_trimis'=>'Mesaj Trimis','client_creat'=>'Client Creat','client_editat'=>'Client Editat','client_sters'=>'Client Sters','pgr_creat'=>'Programare Noua','pgr_editat'=>'Programare Editata','pgr_sters'=>'Programare Stearsa','ctr_creat'=>'Contract Nou','ctr_editat'=>'Contract Editat','ctr_sters'=>'Contract Sters','print_creat'=>'Comanda Print','user_creat'=>'User Creat','user_sters'=>'User Sters','parola_schimbata'=>'Parola Schimbata']; $ac=['login'=>'#16a34a','logout'=>'#64748b','ticket_creat'=>'#1e7fc8','ticket_editat'=>'#d97706','ticket_sters'=>'#dc2626','status_schimbat'=>'#6b48c8','mesaj_trimis'=>'#16a34a','client_creat'=>'#1e7fc8','pgr_creat'=>'#6b48c8','ctr_creat'=>'#16a34a','print_creat'=>'#e0457b','parola_schimbata'=>'#dc2626'];?>
Reset inregistrari
'🔧','pgr'=>'📅','ctr'=>'🤝','print'=>'🖨️'];foreach($d['logs'] as $l):$col=$ac[$l['action']]??'#64748b';?>
Data/OraUtilizatorModulActiuneObiectDetalii
Nicio inregistrare.
👤 Profilul Meu
·
Ultima auth.:

🔑 Schimba Parola
<?=APP_NAME?> · Login
HEL of a SERVICE
HEL of a SERVICE
All-In-One HUB · Service · Print · Contracte
· v1.0