Принудительно загрузить актуальные заказы, клиентов и остальные данные с сервера, заменив локальную копию на этом устройстве. Перед загрузкой автоматически создаётся резервная копия.
`:''}
@@ -2914,6 +2915,15 @@ window.SUN_LEGACY_CATALOG_V175=[{"id":"1","name":"Фуршетный бокс
$('sunCloudSignInV2')?.addEventListener('click',()=>signIn(false));
$('sunCloudSignUpV2')?.addEventListener('click',()=>signIn(true));
$('sunCloudSignOutV2')?.addEventListener('click',signOutAndReload);
+ $('sunAccountChangePasswordV1')?.addEventListener('click',async()=>{
+ const p1i=$('sunAccountNewPasswordV1'),p2i=$('sunAccountNewPassword2V1');
+ const p1=String(p1i?.value||''),p2=String(p2i?.value||'');
+ if(p1.length<8)return toast('Новый пароль должен содержать минимум 8 символов.','warn');
+ if(p1!==p2)return toast('Пароли не совпадают.','warn');
+ if(!client)return toast('Облачный сервис не подключён.','error');
+ try{const r=await client.auth.updateUser({password:p1});if(r.error)throw r.error;if(p1i)p1i.value='';if(p2i)p2i.value='';toast('Пароль изменён.','success');}
+ catch(e){toast(String(e?.message||e||'Не удалось изменить пароль.'),'error');}
+ });
$('sunCloudCreateWorkspaceV2')?.addEventListener('click',createWorkspace);
$('sunCloudReloadMembershipsV2')?.addEventListener('click',async()=>{const tenantSwitched=await loadMemberships();if(tenantSwitched){location.reload();return;}renderCloudUI();if(workspace){subscribeRealtime();await pullRemote({replace:true,quiet:true});}});
$('sunCloudMigrateV2')?.addEventListener('click',migrateLocalToCloud);
@@ -3564,14 +3574,12 @@ window.SUN_LEGACY_CATALOG_V175=[{"id":"1","name":"Фуршетный бокс
bindPasswordEyes(gate);const btn=gate.querySelector('#sunInviteJoinV27');const run=async()=>{const c=client(),email=String(preview.email||'').trim(),name=String(gate.querySelector('#sunInviteNameV27')?.value||'').trim(),password=String(gate.querySelector('#sunInvitePasswordV27')?.value||''),password2=String(gate.querySelector('#sunInvitePassword2V27')?.value||''),err=gate.querySelector('#sunGateErrorV3');if(password.length<6){err.textContent='Пароль должен содержать минимум 6 символов.';return;}if(password!==password2){err.textContent='Пароли не совпадают.';return;}btn.disabled=true;err.textContent='Проверяю аккаунт…';try{let r=await c.auth.signInWithPassword({email,password});if(r.error){r=await c.auth.signUp({email,password,options:{data:{name,registration_source:'caterium_invite_signup'}}});if(r.error)throw r.error;if(!r.data.session){const retry=await c.auth.signInWithPassword({email,password});if(retry.error)throw new Error('Этот email уже зарегистрирован. Введите пароль от существующего аккаунта.');r=retry;}}const userId=r.data.user?.id||r.data.session?.user?.id||'';if(userId)sessionStorage.setItem(`sunCloudQuickPinUnlockedV3:${userId}`,'1');err.textContent='Аккаунт готов. Подключаю компанию…';setTimeout(()=>finishInvite(token,gate),180);}catch(e){err.textContent=String(e?.message||e||'Не удалось войти или создать аккаунт.');btn.disabled=false;}};btn.onclick=run;gate.querySelector('#sunInvitePassword2V27').addEventListener('keydown',e=>{if(e.key==='Enter')run()});
}
- function mustChangePassword(user){return Boolean(user?.user_metadata?.must_change_password);}
-
- function showPasswordChangeGate(gate,c,user,onDone){
- gate.innerHTML=`
Создайте новый пароль
Первый вход сотрудника
Временный пароль сработал. Теперь придумайте свой постоянный пароль.
`;
- bindPasswordEyes(gate);
- const run=async()=>{const p1=String(gate.querySelector('#sunEmployeeNewPasswordV28')?.value||''),p2=String(gate.querySelector('#sunEmployeeNewPassword2V28')?.value||''),err=gate.querySelector('#sunGateErrorV3'),btn=gate.querySelector('#sunEmployeeSavePasswordV28');if(p1.length<8){err.textContent='Новый пароль должен содержать минимум 8 символов.';return;}if(p1!==p2){err.textContent='Пароли не совпадают.';return;}btn.disabled=true;err.textContent='Сохраняю пароль…';try{const nextData={...(user?.user_metadata||{}),must_change_password:false};const r=await c.auth.updateUser({password:p1,data:nextData});if(r.error)throw r.error;err.textContent='Пароль сохранён.';setTimeout(()=>onDone?.(),120);}catch(e){err.textContent=String(e?.message||e||'Не удалось изменить пароль.');btn.disabled=false;}};
- gate.querySelector('#sunEmployeeSavePasswordV28').onclick=run;gate.querySelector('#sunEmployeeNewPassword2V28').addEventListener('keydown',e=>{if(e.key==='Enter')run();});
- }
+ // Password changes now happen from account settings (see cloud-sync-v2.js's
+ // renderCloudUI "Пароль" box) instead of a forced post-login gate: the old
+ // gate raced with membership loading (loadMemberships finishing and
+ // ensureAuthGate's periodic poll tearing the gate down as soon as
+ // signedIn+workspace was true) and could disappear before the employee
+ // ever saw it.
function ensureAuthGate(){
const st=cloud()?.status?.();if(!st?.connected)return;
@@ -3593,7 +3601,7 @@ window.SUN_LEGACY_CATALOG_V175=[{"id":"1","name":"Фуршетный бокс
gate.innerHTML=`
`;document.body.appendChild(gate);bindPasswordEyes(gate);
const emailInput=gate.querySelector('#sunGateEmailV3'),passwordInput=gate.querySelector('#sunGatePasswordV3'),password2Input=gate.querySelector('#sunGatePassword2V27'),companyInput=gate.querySelector('#sunGateCompanyV3'),submitBtn=gate.querySelector('#sunGateSubmitV3'),gateError=gate.querySelector('#sunGateErrorV3');let registerMode=false;
const setMode=(registration)=>{registerMode=Boolean(registration);gate.querySelector('#sunGateRegisterFieldsV27').hidden=!registerMode;gate.querySelector('#sunGateConfirmWrapV27').hidden=!registerMode;gate.querySelector('#sunGateTitleV3').textContent=registerMode?'Создать аккаунт Caterium':'Вход в Caterium';gate.querySelector('#sunGateSubtitleV3').textContent=registerMode?'Заполните данные — после регистрации Caterium откроется автоматически':'Введите данные своего аккаунта';submitBtn.textContent=registerMode?'Создать аккаунт':'Войти';gate.querySelector('#sunGateSwitchTextV27').textContent=registerMode?'Уже есть аккаунт?':'Нет аккаунта?';gate.querySelector('#sunGateSwitchV27').textContent=registerMode?'Войти':'Создать аккаунт';passwordInput.autocomplete=registerMode?'new-password':'current-password';gateError.textContent='';if(registerMode)setTimeout(()=>companyInput.focus(),30);else setTimeout(()=>emailInput.focus(),30)};
- async function auth(){const c=client(),email=emailInput.value.trim(),password=passwordInput.value,password2=password2Input.value,companyName=String(companyInput.value||'').trim();if(!c){gateError.textContent='Облачный сервис не подключён.';return;}if(registerMode&&!companyName){gateError.textContent='Введите название компании.';return;}if(!email||password.length<6){gateError.textContent='Введите email и пароль минимум из 6 символов.';return;}if(registerMode&&password!==password2){gateError.textContent='Пароли не совпадают.';return;}submitBtn.disabled=true;gateError.textContent=registerMode?'Создаю аккаунт…':'Выполняю вход…';try{let r;if(registerMode){savePendingRegistration(email,companyName);const existing=await c.auth.signInWithPassword({email,password});if(!existing.error&&existing.data.session){r=existing;}else{r=await c.auth.signUp({email,password,options:{data:{company_name:companyName,registration_source:'caterium_public_signup'}}});if(r.error)throw r.error;if(!r.data.session){const retry=await c.auth.signInWithPassword({email,password});if(retry.error){clearPendingRegistration();throw new Error('Этот email уже зарегистрирован. Войдите в аккаунт или восстановите пароль.');}r=retry;}}}else r=await c.auth.signInWithPassword({email,password});if(r.error)throw r.error;const authUser=r.data.user||r.data.session?.user||null;const userId=authUser?.id||'';if(userId)sessionStorage.setItem(`sunCloudQuickPinUnlockedV3:${userId}`,'1');if(!registerMode&&mustChangePassword(authUser)){showPasswordChangeGate(gate,c,authUser,()=>{gate.remove();document.body.classList.remove('sun-cloud-auth-required');setTimeout(()=>ensureAuthGate(),80);});return;}gateError.textContent=registerMode?'Аккаунт готов. Создаю компанию…':'Вход выполнен. Загружаю рабочую базу…';setTimeout(async()=>{await cloud()?.reloadMemberships?.();if(registerMode&&workspace()){clearPendingRegistration();gate.remove();document.body.classList.remove('sun-cloud-auth-required');await cloud()?.pull?.();applyNavPermissions();return;}if(getPendingRegistration(email)&&!workspace()){await finishPendingRegistration(gate,email);return;}if(workspace()){gate.remove();document.body.classList.remove('sun-cloud-auth-required');await cloud()?.pull?.();applyNavPermissions();}else{gate.remove();ensureAuthGate();}},180);}catch(err){gateError.textContent=String(err?.message||err||'Не удалось выполнить операцию.')}finally{submitBtn.disabled=false}}
+ async function auth(){const c=client(),email=emailInput.value.trim(),password=passwordInput.value,password2=password2Input.value,companyName=String(companyInput.value||'').trim();if(!c){gateError.textContent='Облачный сервис не подключён.';return;}if(registerMode&&!companyName){gateError.textContent='Введите название компании.';return;}if(!email||password.length<6){gateError.textContent='Введите email и пароль минимум из 6 символов.';return;}if(registerMode&&password!==password2){gateError.textContent='Пароли не совпадают.';return;}submitBtn.disabled=true;gateError.textContent=registerMode?'Создаю аккаунт…':'Выполняю вход…';try{let r;if(registerMode){savePendingRegistration(email,companyName);const existing=await c.auth.signInWithPassword({email,password});if(!existing.error&&existing.data.session){r=existing;}else{r=await c.auth.signUp({email,password,options:{data:{company_name:companyName,registration_source:'caterium_public_signup'}}});if(r.error)throw r.error;if(!r.data.session){const retry=await c.auth.signInWithPassword({email,password});if(retry.error){clearPendingRegistration();throw new Error('Этот email уже зарегистрирован. Войдите в аккаунт или восстановите пароль.');}r=retry;}}}else r=await c.auth.signInWithPassword({email,password});if(r.error)throw r.error;const authUser=r.data.user||r.data.session?.user||null;const userId=authUser?.id||'';if(userId)sessionStorage.setItem(`sunCloudQuickPinUnlockedV3:${userId}`,'1');gateError.textContent=registerMode?'Аккаунт готов. Создаю компанию…':'Вход выполнен. Загружаю рабочую базу…';setTimeout(async()=>{await cloud()?.reloadMemberships?.();if(registerMode&&workspace()){clearPendingRegistration();gate.remove();document.body.classList.remove('sun-cloud-auth-required');await cloud()?.pull?.();applyNavPermissions();return;}if(getPendingRegistration(email)&&!workspace()){await finishPendingRegistration(gate,email);return;}if(workspace()){gate.remove();document.body.classList.remove('sun-cloud-auth-required');await cloud()?.pull?.();applyNavPermissions();}else{gate.remove();ensureAuthGate();}},180);}catch(err){gateError.textContent=String(err?.message||err||'Не удалось выполнить операцию.')}finally{submitBtn.disabled=false}}
gate.querySelector('#sunGateSwitchV27').onclick=()=>setMode(!registerMode);submitBtn.onclick=auth;passwordInput.addEventListener('keydown',e=>{if(e.key==='Enter'&&!registerMode)auth()});password2Input.addEventListener('keydown',e=>{if(e.key==='Enter'&®isterMode)auth()});setMode(false);
}