<title>ClientWorkKZ DEV (All-in-One)</title>
<script src="https://maps.googleapis.com/maps/api/js?key=ВАШ_API_KEY"></script>
<style>
body{margin:0;font-family:Arial;background:#f0fdf4;color:#000}
header{background:#25D366;padding:15px;text-align:center;font-weight:bold}
.wrap{padding:12px}
.card{background:#fff;border-radius:12px;padding:12px;margin-bottom:10px}
input,select,textarea{width:100%;padding:10px;margin-top:5px;border-radius:8px;border:1px solid #ccc}
button{width:100%;padding:10px;margin-top:5px;border:none;border-radius:8px;background:#25D366;font-weight:bold}
.adminBtn{background:#FFD700}
.job,.chat{background:#eaffea;padding:10px;border-radius:8px;margin-top:5px}
.hidden{display:none}
#map{height:220px;border-radius:10px;margin-top:6px}
.small{font-size:12px;color:#555}
</style>
ClientWorkKZ DEV
Вход
Клиент
Исполнитель
Войти
Админ: номер 87027591047, пароль @$$_%1984
Создать заказ
Создать
💬 Чат (без админа)
<textarea id="msg" placeholder="Сообщение"></textarea>
Отправить
📞 Позвонить (demo)
Админ панель
Заблокированные
Kaspi
Готово
Выход
<script>
/* ===== CONFIG ===== */
const ADMIN_PHONE="87027591047";
const ADMIN_PASS="@$$_%1984";
/* ===== STORAGE ===== */
let users = JSON.parse(localStorage.users||"{}"); // {phone:{role,blocked}}
let orders = JSON.parse(localStorage.orders||"[]");
let chats = JSON.parse(localStorage.chats||"{}"); // room:[{from,text}]
let kaspi = JSON.parse(localStorage.kaspi||'{"name":"Берик","number":"87027591047"}');
let current="", role="", isAdmin=false;
let lat=null, lng=null;
let activeRoom="";
/* ===== HELPERS ===== */
function save(){
localStorage.users = JSON.stringify(users);
localStorage.orders = JSON.stringify(orders);
localStorage.chats = JSON.stringify(chats);
localStorage.kaspi = JSON.stringify(kaspi);
}
function login(){
const p = document.getElementById("phone").value.trim();
const pass = document.getElementById("adminPass").value.trim();
const r = document.getElementById("role").value;
if(!p){ alert("Введите номер"); return; }
if(p === ADMIN_PHONE){
if(pass !== ADMIN_PASS){ alert("Неверный пароль админа"); return; }
isAdmin = true;
role = "admin";
document.getElementById("adminPanel").classList.remove("hidden");
} else {
role = r;
}
current = p;
if(!users[p]){
users[p] = { role, blocked:false };
} else {
// не даём стать админом кому-то ещё
if(p !== ADMIN_PHONE && users[p].role === "admin"){
users[p].role = "client";
}
users[p].role = role;
}
save();
document.getElementById("loginBox").style.display="none";
document.getElementById("main").classList.remove("hidden");
render();
}
/* ===== GEO ===== */
function getLocation(){
if(!navigator.geolocation){ alert("Нет геолокации"); return; }
navigator.geolocation.getCurrentPosition(pos=>{
lat = pos.coords.latitude;
lng = pos.coords.longitude;
document.getElementById("coords").innerText = lat.toFixed(5)+", "+lng.toFixed(5);
if(window.google && google.maps){
const map = new google.maps.Map(document.getElementById("map"),{
center:{lat,lng}, zoom:14
});
new google.maps.Marker({position:{lat,lng}, map});
}
});
}
/* ===== ORDERS ===== */
function createOrder(){
if(users[current]?.blocked){
alert("Вы заблокированы\nKASPI\n"+kaspi.number+" "+kaspi.name);
return;
}
const myCount = orders.filter(o=>o.user===current).length;
if(myCount >= 5){
users[current].blocked = true;
save();
alert("Лимит достигнут!\nKASPI\n"+kaspi.number+" "+kaspi.name);
return;
}
const t = document.getElementById("title").value.trim();
const p = document.getElementById("price").value.trim();
if(!t){ alert("Введите название"); return; }
orders.unshift({
id: Date.now(),
title:t,
price:p,
user:current,
worker:null,
status:"Ожидает",
lat, lng
});
save();
render();
}
function takeOrder(id){
const o = orders.find(x=>x.id===id);
if(!o || o.worker) return;
o.worker = current;
o.status = "В работе";
activeRoom = o.user+"-"+o.worker;
document.getElementById("chatBox").classList.remove("hidden");
save();
render();
}
function finishOrder(id){
const o = orders.find(x=>x.id===id);
if(!o) return;
o.status = "Завершён";
save();
render();
}
/* ===== CHAT (client ↔ worker) ===== */
function sendMsg(){
const text = document.getElementById("msg").value.trim();
if(!text || !activeRoom) return;
if(!chats[activeRoom]) chats[activeRoom] = [];
chats[activeRoom].push({ from: current, text });
document.getElementById("msg").value="";
save();
renderChat();
}
function renderChat(){
const box = document.getElementById("chat");
box.innerHTML = "";
const arr = chats[activeRoom] || [];
arr.forEach(m=>{
box.innerHTML += `
${m.from}: ${m.text}
`;
});
}
/* ===== CALL (demo) ===== */
function callUser(){
alert("Демо звонка. В проде подключается WebRTC/SDK.");
}
/* ===== ADMIN ===== */
function saveKaspi(){
kaspi.name = document.getElementById("kaspiName").value || kaspi.name;
kaspi.number = document.getElementById("kaspiNumber").value || kaspi.number;
save();
alert("Реквизиты обновлены");
}
function unblock(u){
if(users[u]){
users[u].blocked = false;
save();
render();
}
}
/* ===== RENDER ===== */
function render(){
const ordersBox = document.getElementById("orders");
const blockedBox = document.getElementById("blockedList");
ordersBox.innerHTML = "";
blockedBox.innerHTML = "";
orders.forEach(o=>{
ordersBox.innerHTML += `
${o.title}
Цена: ${o.price || "-"} ₸
Статус: ${o.status}
Клиент: ${o.user}
Исполнитель: ${o.worker || "-"}
📍 ${o.lat ? o.lat.toFixed(3)+", "+o.lng.toFixed(3) : "нет"}
${
role==="worker" && !o.worker
? `Взять`
: ""
}
${
role==="worker" && o.worker===current && o.status==="В работе"
? `Завершить`
: ""
}
`;
});
if(isAdmin){
Object.keys(users).forEach(u=>{
if(users[u].blocked){
blockedBox.innerHTML += `
${u}
Разблокировать
`;
}
});
}
renderChat();
}
/* ===== LOGOUT ===== */
function logout(){
location.reload();
}
</script>
Вход
Клиент Исполнитель Войти📍 Локация
ОпределитьСоздать заказ
СоздатьЗаказы
💬 Чат (без админа)
<textarea id="msg" placeholder="Сообщение"></textarea> Отправить 📞 Позвонить (demo)Админ панель
Заблокированные
Kaspi
ГотовоВыход
Цена: ${o.price || "-"} ₸
Статус: ${o.status}
Клиент: ${o.user}
Исполнитель: ${o.worker || "-"}
📍 ${o.lat ? o.lat.toFixed(3)+", "+o.lng.toFixed(3) : "нет"} ${ role==="worker" && !o.worker ? `Взять` : "" } ${ role==="worker" && o.worker===current && o.status==="В работе" ? `Завершить` : "" }