Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/select menu admin settings #1387

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ interface Iproperties {
}
const SettingsSidebar: FC<Iproperties> = ({ sideNavitems = sideItems }) => {
const pathname = usePathname();
const currentPath =
pathname?.split("/").length == 2 ? "general" : pathname?.split("/")[3];
const urlPathnames = pathname
?.split("/")
.filter((segment: string) => segment !== "");
const currentPath = urlPathnames.length == 3 ? "general" : urlPathnames.pop();
const organizationPath = pathname?.split("/")[4];
const { organizations } = useOrgContext();
const { data: session } = useSession();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,73 @@
"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import axios from "axios";
import { Eye, EyeOff } from "lucide-react";
import { useSession } from "next-auth/react";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { ChangeEvent, useState } from "react";

import { getApiUrl } from "~/actions/getApiUrl";
import CustomButton from "~/components/common/common-button/common-button";
import CustomInput from "~/components/common/input/input";
import PasswordSuccessfulModal from "~/components/common/modals/password-successful";
import { toast } from "~/components/ui/use-toast";
import { cn } from "~/lib/utils";
import { passwordSchema, type PasswordFormData } from "./schema";

type PasswordField = "current" | "new" | "confirmNew";

const Password = () => {
const { data } = useSession();

const [open, setOpen] = useState<boolean>(false);

const [isPending, setIsPending] = useState(false);

const {
register,
handleSubmit,
reset,
formState: { errors, isValid },
} = useForm<PasswordFormData>({
resolver: zodResolver(passwordSchema),
mode: "all",
const [showPassword, setShowPassword] = useState({
current: false,
new: false,
confirmNew: false,
});

const submitHandler = async (values: PasswordFormData) => {
const [formData, setFormData] = useState({
oldPassword: "",
password: "",
confirmPassword: "",
});
const formDataHandler = (
event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
setFormData((previous) => ({
...previous,
[event.target.name]: event.target.value,
}));
};

const submit = async () => {
if (formData.password !== formData.confirmPassword) {
return toast({
title: "Warning!",
description: "Password does not match",
});
}
try {
setIsPending(true);
const baseUrl = await getApiUrl();
const API_URL = `${baseUrl}/api/v1/auth/change-password`;

const payload = {
old_password: values.currentPassword,
new_password: values.newPassword,
confirm_new_password: values.confirmPassword,
oldPassword: formData.oldPassword,
newPassword: formData.password,
};
const baseUrl = await getApiUrl();
const API_URL = `${baseUrl}/api/v1/auth/password`;

await axios.put(API_URL, payload, {
await axios.post(API_URL, payload, {
headers: {
Authorization: `Bearer ${data?.access_token}`,
},
});
setOpen(true);
reset({ currentPassword: "", newPassword: "", confirmPassword: "" });
setFormData({
oldPassword: "",
password: "",
confirmPassword: "",
});
} catch (error) {
const errorMessage = (error as HttpError)?.response?.data?.message;
toast({
Expand All @@ -59,6 +80,16 @@ const Password = () => {
}
};

const togglePasswordVisibility = (field: PasswordField) => {
setShowPassword((previousState) => ({
...previousState,
[field]: !previousState[field],
}));
};

const disabled =
!formData.confirmPassword || !formData.oldPassword || !formData.password;

return (
<div className="w-full px-3 pt-[50px] md:px-8">
<div className="mb-8">
Expand All @@ -69,96 +100,78 @@ const Password = () => {
Update password for enhanced account security
</p>
</div>
<form onSubmit={handleSubmit(submitHandler)}>
<div>
<div className="mb-6 grid gap-4">
<div className="">
<div className="flex w-full flex-col gap-2 rounded-md border-border text-sm text-primary transition-colors focus:border-primary focus:outline-none">
<label className="flex border-0 text-sm font-medium text-foreground">
Current Password
</label>
<div className="flex w-full items-center">
<input
className={cn(
"flex h-10 w-full flex-col gap-2 rounded-md border border-border bg-background px-4 py-2 text-sm text-foreground ring-offset-background transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary focus-visible:border-primary focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
errors.currentPassword && "border-red-500",
)}
placeholder="Enter current password"
type="password"
{...register("currentPassword")}
/>
</div>
</div>
{errors.currentPassword && (
<p className="mt-0.5 text-xs text-red-500">
{errors.currentPassword?.message}
</p>
)}
<div className="relative">
<CustomInput
placeholder="Enter current password"
label="Current Password"
className="border-border"
type={`${showPassword.current ? "text" : "password"}`}
name="oldPassword"
value={formData.oldPassword}
onChange={formDataHandler}
/>
<span
className="absolute right-2 top-9 cursor-pointer"
onClick={() => togglePasswordVisibility("current")}
>
{showPassword.current ? <EyeOff size={20} /> : <Eye size={20} />}
</span>
</div>
<div className="">
<div className="flex w-full flex-col gap-2 rounded-md border-border text-sm text-primary transition-colors focus:border-primary focus:outline-none">
<label className="flex border-0 text-sm font-medium text-foreground">
New Password
</label>
<div className="flex w-full items-center">
<input
className={cn(
"flex h-10 w-full flex-col gap-2 rounded-md border border-border bg-background px-4 py-2 text-sm text-foreground ring-offset-background transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary focus-visible:border-primary focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
errors.newPassword && "border-red-500",
)}
placeholder="Enter new password"
type="password"
{...register("newPassword")}
/>
</div>
</div>
{errors.newPassword && (
<p className="mt-0.5 text-xs text-red-500">
{errors.newPassword?.message}
</p>
)}
<div className="relative">
<CustomInput
placeholder="Enter new password"
label="New Password"
className="border-border"
type={`${showPassword.new ? "text" : "password"}`}
name="password"
value={formData.password}
onChange={formDataHandler}
/>
<span
className="absolute right-2 top-9 cursor-pointer"
onClick={() => togglePasswordVisibility("new")}
>
{showPassword.new ? <EyeOff size={20} /> : <Eye size={20} />}
</span>
</div>
<div className="">
<div className="flex w-full flex-col gap-2 rounded-md border-border text-sm text-primary transition-colors focus:border-primary focus:outline-none">
<label className="flex border-0 text-sm font-medium text-foreground">
Confirm new password
</label>
<div className="flex w-full items-center">
<input
className={cn(
"flex h-10 w-full flex-col gap-2 rounded-md border border-border bg-background px-4 py-2 text-sm text-foreground ring-offset-background transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary focus-visible:border-primary focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
errors.confirmPassword && "border-red-500",
)}
placeholder="Confrim new Password"
type="password"
{...register("confirmPassword")}
/>
</div>
</div>
{errors.confirmPassword && (
<p className="mt-0.5 text-xs text-red-500">
{errors.confirmPassword?.message}
</p>
)}
<div className="relative">
<CustomInput
placeholder="Confirm new password"
label="Confirm new Password"
className="border-border"
type={`${showPassword.confirmNew ? "text" : "password"}`}
name="confirmPassword"
value={formData.confirmPassword}
onChange={formDataHandler}
/>
<span
className="absolute right-2 top-9 cursor-pointer"
onClick={() => togglePasswordVisibility("confirmNew")}
>
{showPassword.confirmNew ? (
<EyeOff size={20} />
) : (
<Eye size={20} />
)}
</span>
</div>
</div>
<div className="flex items-center justify-start gap-6">
<CustomButton
type="button"
variant="outline"
onClick={() => setOpen(false)}
>
<CustomButton variant="outline" onClick={() => setOpen(false)}>
Cancel
</CustomButton>
<CustomButton
isDisabled={!isValid}
type="submit"
className={`bg-primary ${isPending && "opacity-50"}`}
isDisabled={disabled}
onClick={submit}
className="bg-primary"
isLoading={isPending}
>
Update Password
</CustomButton>
</div>
</form>
</div>
<PasswordSuccessfulModal onClose={() => setOpen(!open)} show={open} />
</div>
);
Expand Down
Loading