chore: change password form

pull/3813/head
Arik Chakma 2 years ago
parent f5658e1980
commit 9a145cb785
  1. 176
      src/components/Setting/ChangePasswordForm.tsx
  2. 117
      src/components/Setting/UpdateProfileForm.tsx
  3. 6
      src/pages/settings/change-password.astro

@ -0,0 +1,176 @@
import { useState } from 'preact/hooks';
import Cookies from 'js-cookie';
import { TOKEN_COOKIE_NAME } from '../../lib/utils';
export default function ChangePasswordForm() {
const [currentPassword, setCurrentPassword] = useState('');
const [newPassword, setNewPassword] = useState('');
const [newPasswordConfirmation, setNewPasswordConfirmation] = useState('');
const [error, setError] = useState('');
const [successMessage, setSuccessMessage] = useState('');
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = (e: Event) => {
e.preventDefault();
setIsLoading(true);
if (newPassword !== newPasswordConfirmation) {
setError('New password and confirmation do not match');
setIsLoading(false);
return;
}
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append(
'Cookie',
`${TOKEN_COOKIE_NAME}=${Cookies.get(TOKEN_COOKIE_NAME)}`
);
fetch('http://localhost:8080/v1-update-password', {
method: 'POST',
credentials: 'include',
headers,
body: JSON.stringify({
oldPassword: currentPassword,
password: newPassword,
confirmPassword: newPasswordConfirmation,
}),
})
.then(async (res) => {
const json = await res.json();
if (res.ok) {
return json;
} else {
throw new Error(json.message);
}
})
.then((data) => {
setIsLoading(false);
setCurrentPassword('');
setNewPassword('');
setNewPasswordConfirmation('');
setSuccessMessage('Password updated successfully');
})
.catch((err) => {
setIsLoading(false);
setError(err.message);
});
};
console.log(currentPassword, newPassword, newPasswordConfirmation);
console.log(`${TOKEN_COOKIE_NAME}=${Cookies.get(TOKEN_COOKIE_NAME)}`);
return (
<form onSubmit={handleSubmit}>
<h2 className="text-3xl font-bold sm:text-4xl">Password</h2>
<p className="mt-2">Manage settings for your account passwords</p>
<div className="mt-8 space-y-4">
<div className="flex w-full flex-col">
<label
for="current-password"
className="text-sm leading-none text-slate-500"
>
Current Password
</label>
<input
type="password"
name="current-password"
id="current-password"
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
required
minLength={6}
placeholder="Current password"
value={currentPassword}
onChange={(e) =>
setCurrentPassword((e.target as HTMLInputElement).value)
}
/>
</div>
<div className="flex w-full flex-col">
<label
for="new-password"
className="text-sm leading-none text-slate-500"
>
New Password
</label>
<input
type="password"
name="new-password"
id="new-password"
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
required
minLength={6}
placeholder="New password"
value={newPassword}
onChange={(e) =>
setNewPassword((e.target as HTMLInputElement).value)
}
/>
</div>
<div className="flex w-full flex-col">
<label
for="new-password-confirmation"
className="text-sm leading-none text-slate-500"
>
New Password Confirm
</label>
<input
type="password"
name="new-password-confirmation"
id="new-password-confirmation"
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
required
minLength={6}
placeholder="New password confirm"
value={newPasswordConfirmation}
onChange={(e) =>
setNewPasswordConfirmation((e.target as HTMLInputElement).value)
}
/>
</div>
{error && (
<div className="text-sm font-medium text-red-500">
<p>{error}</p>
</div>
)}
{successMessage && (
<div className="text-sm font-medium text-green-500">
<p>{successMessage}</p>
</div>
)}
<button
className="!mt-5 inline-flex h-10 min-w-[120px] items-center justify-center rounded-lg border border-slate-300 bg-black p-2 px-4 text-sm font-medium text-white outline-none transition duration-150 ease-in-out focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:opacity-60"
type="submit"
>
{isLoading ? (
<svg
class={`h-5 w-5 animate-spin text-white`}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="stroke-[4px] opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
) : (
'Change'
)}
</button>
</div>
</form>
);
}

@ -0,0 +1,117 @@
import { useState } from 'preact/hooks';
export default function UpdateProfileForm() {
const [name, setName] = useState('');
const [github, setGithub] = useState('');
const [linkedin, setLinkedin] = useState('');
const [website, setWebsite] = useState('');
const [error, setError] = useState('');
const [successMessage, setSuccessMessage] = useState('');
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = (e: Event) => {
e.preventDefault();
setIsLoading(true);
fetch('http://localhost:8080/v1-update-profile', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name,
github,
linkedin,
website,
}),
});
};
return (
<form>
<h2 className="text-3xl font-bold sm:text-4xl">Update Profile</h2>
<p className="mt-2">Manage settings for your roadmap.sh profile</p>
<div className="mt-8 space-y-4">
<div className="flex w-full flex-col">
<label
for="name"
className='text-sm leading-none text-slate-500 after:text-red-400 after:content-["*"]'
>
Name
</label>
<input
type="text"
name="name"
id="name"
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
required
placeholder="Arik Chakma"
/>
</div>
<div className="flex w-full flex-col">
<label
for="email"
className='text-sm leading-none text-slate-500 after:text-red-400 after:content-["*"]'
>
Email
</label>
<input
type="email"
name="email"
id="email"
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
required
disabled
placeholder="arik@roadmap.sh"
/>
</div>
<div className="flex w-full flex-col">
<label for="github" className="text-sm leading-none text-slate-500">
Github Username
</label>
<input
type="text"
name="github"
id="github"
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
placeholder="arikchakma"
/>
</div>
<div className="flex w-full flex-col">
<label for="linkedin" className="text-sm leading-none text-slate-500">
LinkedIn Url
</label>
<input
type="text"
name="linkedin"
id="linkedin"
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
placeholder="https://www.linkedin.com/in/arikchakma/"
/>
</div>
<div className="flex w-full flex-col">
<label for="website" className="text-sm leading-none text-slate-500">
Website
</label>
<input
type="text"
name="website"
id="website"
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
placeholder="https://arikko.dev"
/>
</div>
<button
className="!mt-5 inline-flex h-10 items-center justify-center rounded-lg border border-slate-300 bg-black p-2 px-4 text-sm font-medium text-white outline-none transition duration-150 ease-in-out focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:opacity-60"
type="button"
>
Update
</button>
</div>
</form>
);
}

@ -1,11 +1,11 @@
--- ---
import ChangePassword from '../../components/Setting/ChangePassword.astro'; import ChangePasswordForm from '../../components/Setting/ChangePasswordForm';
import SettingSidebar from '../../components/Setting/SettingSidebar.astro'; import SettingSidebar from '../../components/Setting/SettingSidebar.astro';
import SettingLayout from '../../layouts/SettingLayout.astro'; import SettingLayout from '../../layouts/SettingLayout.astro';
--- ---
<SettingLayout title='Change Password' description=''> <SettingLayout title='Change Password' description=''>
<SettingSidebar pageUrl='change-password' name="Change Password"> <SettingSidebar pageUrl='change-password' name='Change Password'>
<ChangePassword /> <ChangePasswordForm client:load />
</SettingSidebar> </SettingSidebar>
</SettingLayout> </SettingLayout>

Loading…
Cancel
Save