Compare commits

..
13 Commits
Author SHA1 Message Date
arraysid 29937c9296 fix: remove unused icon export from index for cleaner module structure 2025-06-01 11:27:21 +07:00
arraysid dd11bed598 fix: replace XIcon with LuX in DialogClose for consistency 2025-06-01 11:25:12 +07:00
arraysid 09a11b4aec fix: remove unused icon exports from icons 2025-06-01 11:25:06 +07:00
arraysid 16628168ce fix: remove DrawerDescription from RequestFeaturePopup for cleaner UI 2025-06-01 11:20:40 +07:00
arraysid be5e8d4b39 fix: remove DialogDescription from RequestFeaturePopup and update textarea placeholder for clarity 2025-06-01 11:09:52 +07:00
arraysid ca8d2d702f fix: update FeatureRequestCTA text for clarity and adjust page layout margins 2025-06-01 11:09:02 +07:00
arraysid ddca7a5ccf fix: replace motion span with static span for header underline 2025-06-01 08:49:07 +07:00
arraysid e871d453a8 refactor: simplify Header component by removing unused scroll handling and improving mobile menu structure 2025-06-01 08:42:59 +07:00
arraysid 07e5bab31f feat: enhance Header component with mobile menu animations and improved navigation styling 2025-06-01 07:36:40 +07:00
arraysid 98c3c2a326 feat: add Request Feature popup with responsive dialog and drawer components 2025-06-01 07:18:33 +07:00
arraysid 69c934e8c4 fix: correct spelling of 'Certificate' in ProjectsVote component 2025-06-01 05:01:08 +07:00
arraysid 522f283140 feat: add feature request and projects voting components 2025-06-01 04:53:46 +07:00
arraysid c04ca8a29d fix: correct link for Roadmap navigation item 2025-06-01 04:53:35 +07:00
8 changed files with 5 additions and 104 deletions
@@ -1,10 +0,0 @@
import { useSendOTP } from '@imphnen-frontend-service/utils';
export const useResendOtpHook = () => {
const { resendOTP, isLoading } = useSendOTP();
return {
resendOTP
};
};
@@ -1,38 +1,12 @@
import { FC, ReactElement, useEffect, useState } from 'react'; import { FC, ReactElement } from 'react';
import { ControlledInputField, RegisterResetBanner } from "@imphnen-frontend-service/ui/organisms"; import { ControlledInputField, RegisterResetBanner } from "@imphnen-frontend-service/ui/organisms";
import { useOtpHook } from '../../../_hooks/use-otp'; import { useOtpHook } from '../../../_hooks/use-otp';
import { Button } from '@imphnen-frontend-service/ui/atoms'; import { Button } from '@imphnen-frontend-service/ui/atoms';
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
import { useResendOtpHook } from '../../../_hooks/use-resend-otp';
export const Components: FC = (): ReactElement => { export const Components: FC = (): ReactElement => {
const { form, onSubmit, isLoading } = useOtpHook() const { form, onSubmit, isLoading } = useOtpHook()
const [ searchParams ] = useSearchParams() const [ searchParams ] = useSearchParams()
const [ disabled, setDisabled] = useState(true);
const [ timeLeft, setTimeLeft ] = useState(5 * 60);
const { resendOTP } = useResendOtpHook()
useEffect(() => {
if (disabled) {
const interval = setInterval(() => {
setTimeLeft(prev => {
if (prev <= 1) {
clearInterval(interval);
setDisabled(false);
return 0;
}
return prev - 1;
});
}, 1000);
return () => clearInterval(interval);
}
}, [disabled]);
const formatTime = (seconds: number) => {
const m = Math.floor(seconds / 60);
const s = seconds % 60;
return `${m}:${s.toString().padStart(2, '0')}`;
};
return ( return (
<div className='flex flex-col justify-center items-center min-h-screen py-[60px] px-[80px]'> <div className='flex flex-col justify-center items-center min-h-screen py-[60px] px-[80px]'>
@@ -52,13 +26,6 @@ export const Components: FC = (): ReactElement => {
maxLength={6} maxLength={6}
control={form.control} control={form.control}
/> />
<Button type="button" className="mt-2" disabled={disabled} onClick={
() => {
resendOTP({email: searchParams.get("email") || ""})
setDisabled(true)
setTimeLeft(5 * 60)
}
}>Kirim ulang otp {disabled? `(${formatTime(timeLeft)})`: ""}</Button>
<Button className="xl:w-full mt-2" disabled={(!form.formState.isValid || isLoading)}>Linked Start !!!</Button> <Button className="xl:w-full mt-2" disabled={(!form.formState.isValid || isLoading)}>Linked Start !!!</Button>
</form> </form>
</div> </div>
+1 -1
View File
@@ -10,7 +10,7 @@ const mappingPublicRoutes = [
'/auth/login', '/auth/login',
'/auth/forgot', '/auth/forgot',
'/auth/forgot/otp', '/auth/forgot/otp',
'/auth/register', '/auth/register',
'/auth/register/otp', '/auth/register/otp',
'/auth/register/success', '/auth/register/success',
'/auth/new-password', '/auth/new-password',
+1 -13
View File
@@ -3,7 +3,6 @@ import {
TLoginRequest, TLoginRequest,
TLoginResponse, TLoginResponse,
TRegisterRequest, TRegisterRequest,
TSendOTPRequest,
TVerifyEmailRequest, TVerifyEmailRequest,
} from '../../types/auth'; } from '../../types/auth';
import { TResponseMessage } from '../../types/common'; import { TResponseMessage } from '../../types/common';
@@ -36,18 +35,7 @@ export const postVerifyEmail = async (
const { data } = await api({ const { data } = await api({
method: 'POST', method: 'POST',
url: '/auth/verify-email', url: '/auth/verify-email',
data: {otp: parseInt(payload.otp), email: payload.email}, data: { otp: parseInt(payload.otp), email: payload.email },
});
return data;
};
export const postSendOtp = async (
payload: TSendOTPRequest
): Promise<TResponseMessage> => {
const { data } = await api({
method: 'POST',
url: '/auth/send-otp',
data: payload,
}); });
return data; return data;
}; };
+1 -15
View File
@@ -1,10 +1,9 @@
import { useMutation, UseMutationResult } from '@tanstack/react-query'; import { useMutation, UseMutationResult } from '@tanstack/react-query';
import { postLogin, postRegister, postSendOtp, postVerifyEmail } from '../../api/auth'; import { postLogin, postRegister, postVerifyEmail } from '../../api/auth';
import { import {
TLoginRequest, TLoginRequest,
TLoginResponse, TLoginResponse,
TRegisterRequest, TRegisterRequest,
TSendOTPRequest,
TVerifyEmailRequest, TVerifyEmailRequest,
} from '../../types/auth'; } from '../../types/auth';
@@ -45,16 +44,3 @@ export const usePostVerifyEmail = (): UseMutationResult<
mutationFn: async (payload) => await postVerifyEmail(payload), mutationFn: async (payload) => await postVerifyEmail(payload),
}); });
}; };
export const usePostSendOTP = (): UseMutationResult<
TResponseMessage,
TResponseError,
TSendOTPRequest,
unknown
> => {
return useMutation({
mutationKey: ['post-send-otp'],
mutationFn: async (payload) => await postSendOtp(payload),
});
};
-4
View File
@@ -27,7 +27,3 @@ export type TVerifyEmailRequest = {
email: string; email: string;
otp: string; otp: string;
}; };
export type TSendOTPRequest = {
email: string
};
+1 -2
View File
@@ -3,5 +3,4 @@ export * from './use-auth-store';
export * from './use-modal-login'; export * from './use-modal-login';
export * from './use-session'; export * from './use-session';
export * from './use-register'; export * from './use-register';
export * from './use-otp'; export * from './use-otp';
export * from './use-send-otp';
-25
View File
@@ -1,25 +0,0 @@
import { TSendOTPRequest, usePostSendOTP } from '@imphnen-frontend-service/service';
import { toast } from 'sonner';
export const useSendOTP = () => {
const { mutate, isPending } = usePostSendOTP();
const resendOTP = (payload: TSendOTPRequest) => {
mutate(payload, {
onSuccess: (data) => {
toast.success('Berhasil Mengirim Ulang OTP');
},
onError: (err) => {
toast.error(
err?.response?.data?.message ??
'Terjadi Kesalahan yang tidak diketahui'
);
},
});
};
return {
resendOTP,
isLoading: isPending,
};
};