{"id":945,"date":"2025-10-06T00:09:00","date_gmt":"2025-10-06T00:09:00","guid":{"rendered":"https:\/\/protolinker.com\/?page_id=945"},"modified":"2025-10-06T00:14:31","modified_gmt":"2025-10-06T00:14:31","slug":"reset-password","status":"publish","type":"page","link":"https:\/\/protolinker.com\/pt\/reset-password\/","title":{"rendered":"reset"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"945\" class=\"elementor elementor-945\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3a160be e-flex e-con-boxed e-con e-parent\" data-id=\"3a160be\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e6c8b14 elementor-widget elementor-widget-html\" data-id=\"e6c8b14\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<style>\n  .signup-box {\n    font-family: sans-serif;\n    max-width: 400px;\n    width: 100%;\n    margin: 4rem auto;\n    border-radius: 12px;\n    padding: 2rem;\n    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);\n    background: var(--background-color, white);\n    color: var(--text-color, #000);\n    position: relative;\n  }\n  \n    .logo-box {\n    background: #57c5e0;\n    padding: 0;\n    border-radius: 50%;\n    justify-content: center;\n    align-items: center;\n    height: 80px;\n    width: 80px;\n    margin: 0 auto 1rem;\n    overflow: hidden;\n  }\n\n  .logo-box img {\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n    border-radius: 50%;  \n  }\n\n  @media (prefers-color-scheme: dark) {\n    .signup-box {\n      background: #1e1e1e;\n      color: #f0f0f0;\n    }\n\n    .signup-box input {\n      background: #2b2b2b;\n      color: #f0f0f0;\n      border: 1px solid #444;\n    }\n\n    .signup-box .hint {\n      color: #aaa;\n    }\n  }\n\n  .signup-box h2 {\n    text-align: center;\n    font-weight: 600;\n    margin-bottom: 1.5rem;\n    font-size: 1.1rem;\n  }\n\n  input[type=\"password\"] {\n    width: 100%;\n    padding: 10px;\n    border-radius: 6px;\n    border: 1px solid #ccc;\n    margin-top: 4px;\n    margin-bottom: 0.5rem;\n    box-sizing: border-box;\n    font-size: 1rem;\n  }\n\n  .password-wrapper {\n    position: relative;\n    margin-bottom: 1rem;\n  }\n\n  .toggle-password {\n    position: absolute;\n    right: 10px;\n    top: 50%;\n    transform: translateY(-50%);\n    background: none;\n    border: none;\n    color: #00979d;\n    cursor: pointer;\n    font-size: 0.9rem;\n  }\n\n  .hint, .error {\n    font-size: 0.8rem;\n    margin-top: -0.25rem;\n    margin-bottom: 0.75rem;\n  }\n\n  .hint {\n    color: #666;\n  }\n\n  .error {\n    color: #c00;\n  }\n\n  .submit-btn {\n    width: 100%;\n    padding: 10px;\n    font-size: 1rem;\n    background: #ccc;\n    color: white;\n    border: none;\n    border-radius: 8px;\n    cursor: not-allowed;\n    transition: background 0.3s ease;\n  }\n\n  .submit-btn.enabled {\n    background: #00979d;\n    cursor: pointer;\n  }\n<\/style>\n\n<div class=\"signup-box\">\n  <div class=\"logo-box\">\n    <img decoding=\"async\" src=\"https:\/\/protolinker.com\/wp-content\/uploads\/2025\/09\/logo.png\" alt=\"Protolinker Logo\">\n  <\/div>\n\n  <h2>Change your Protolinker password<\/h2>\n\n  <form id=\"changePasswordForm\">\n    <div class=\"password-wrapper\">\n      <input type=\"password\" id=\"password\" placeholder=\"Enter your new password\" required>\n      <button type=\"button\" class=\"toggle-password\" onclick=\"togglePassword('password', this)\">Show<\/button>\n    <\/div>\n    <div id=\"formatError\" class=\"error\" style=\"display:none;\"><\/div>\n\n    <div class=\"password-wrapper\">\n      <input type=\"password\" id=\"confirm-password\" placeholder=\"Confirm your new password\" required>\n      <button type=\"button\" class=\"toggle-password\" onclick=\"togglePassword('confirm-password', this)\">Show<\/button>\n    <\/div>\n    <div id=\"matchError\" class=\"error\" style=\"display:none;\"><\/div>\n\n    <div class=\"hint\">\n      Must contain at least: 1 uppercase, 1 lowercase, 1 numeric character, 1 symbol (!@#$%^&*). Minimum 8 characters.\n    <\/div>\n\n    <button type=\"submit\" id=\"submitBtn\" class=\"submit-btn\">NEXT<\/button>\n  <\/form>\n<\/div>\n\n<script>\n  const newPwInput = document.getElementById(\"password\");\n  const confirmPwInput = document.getElementById(\"confirm-password\");\n  const submitBtn = document.getElementById(\"submitBtn\");\n  const formatError = document.getElementById(\"formatError\");\n  const matchError = document.getElementById(\"matchError\");\n\n  function togglePassword(id, btn) {\n    const input = document.getElementById(id);\n    input.type = input.type === \"password\" ? \"text\" : \"password\";\n    btn.textContent = input.type === \"password\" ? \"Show\" : \"Hide\";\n  }\n\n  function isPasswordStrong(pw) {\n    return \/[A-Z]\/.test(pw) && \n           \/[a-z]\/.test(pw) && \n           \/[0-9]\/.test(pw) && \n           \/[!@#$%^&*]\/.test(pw) && \n           pw.length >= 8;\n  }\n\n  function updateSubmitState() {\n    const pw = newPwInput.value.trim();\n    const confirm = confirmPwInput.value.trim();\n\n    const formatValid = isPasswordStrong(pw);\n    const matchValid = pw === confirm;\n\n    formatError.style.display = formatValid ? \"none\" : \"block\";\n    formatError.textContent = formatValid ? \"\" : \"Password does not meet formatting requirements.\";\n\n    matchError.style.display = matchValid ? \"none\" : \"block\";\n    matchError.textContent = matchValid ? \"\" : \"Passwords do not match.\";\n\n    const enable = formatValid && matchValid;\n    submitBtn.disabled = !enable;\n    submitBtn.classList.toggle(\"enabled\", enable);\n  }\n\n  newPwInput.addEventListener(\"input\", updateSubmitState);\n  confirmPwInput.addEventListener(\"input\", updateSubmitState);\n\n  document.getElementById(\"changePasswordForm\").addEventListener(\"submit\", async (e) => {\n    e.preventDefault();\n\n    const newPassword = newPwInput.value.trim();\n    const confirmPassword = confirmPwInput.value.trim();\n\n    if (newPassword !== confirmPassword) {\n      alert(\"Passwords do not match.\");\n      return;\n    }\n\n    if (!isPasswordStrong(newPassword)) {\n      alert(\"Password does not meet the required format.\");\n      return;\n    }\n\n    const urlParams = new URLSearchParams(window.location.search);\n    const refreshToken = urlParams.get(\"refreshToken\");\n\n    if (!refreshToken) {\n      alert(\"Missing refresh token. Please use the password reset link from your email.\");\n      return;\n    }\n\n    try {\n      \/\/ 1. Exchange refreshToken for accessToken\n      const tokenResponse = await fetch(\"https:\/\/pnjzqfekyquoptxmlbma.auth.sa-east-1.nhost.run\/v1\/token\", {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application\/json\" },\n        body: JSON.stringify({ refreshToken })\n      });\n\n      const tokenData = await tokenResponse.json();\n\n      if (!tokenResponse.ok || !tokenData.accessToken) {\n        alert(`Error retrieving access token: ${tokenData.error || tokenData.message}`);\n        return;\n      }\n\n      const accessToken = tokenData.accessToken;\n\n      \/\/ 2. Use accessToken to change password\n      const changeResponse = await fetch(\"https:\/\/pnjzqfekyquoptxmlbma.auth.sa-east-1.nhost.run\/v1\/user\/password\", {\n        method: \"POST\",\n        headers: { \n          \"Content-Type\": \"application\/json\",\n          \"Authorization\": `Bearer ${accessToken}`\n        },\n        body: JSON.stringify({ newPassword })\n      });\n\n      if (changeResponse.ok) {\n        alert(\"Password changed successfully. Please log in.\");\n        window.location.href = \"\/login\";\n      } else {\n        const result = await changeResponse.json();\n        alert(`Error changing password: ${result.error || result.message}`);\n      }\n\n    } catch (err) {\n      alert(\"Unexpected error. Please try again.\");\n    }\n  });\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Change your Protolinker password Show Show Must contain at least: 1 uppercase, 1 lowercase, 1 numeric character, 1 symbol (!@#$%^&#038;*). Minimum 8 characters. NEXT<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-945","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/protolinker.com\/pt\/wp-json\/wp\/v2\/pages\/945","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/protolinker.com\/pt\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/protolinker.com\/pt\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/protolinker.com\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/protolinker.com\/pt\/wp-json\/wp\/v2\/comments?post=945"}],"version-history":[{"count":0,"href":"https:\/\/protolinker.com\/pt\/wp-json\/wp\/v2\/pages\/945\/revisions"}],"wp:attachment":[{"href":"https:\/\/protolinker.com\/pt\/wp-json\/wp\/v2\/media?parent=945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}