feat: mentor register pages

This commit is contained in:
boboiazumi
2025-07-12 22:15:43 +07:00
parent e1269f4daa
commit eb5ff2e46c
13 changed files with 465 additions and 3 deletions
+1
View File
@@ -1,3 +1,4 @@
export * from './button';
export * from './input';
export * from './textarea';
export * from './select'
+1
View File
@@ -0,0 +1 @@
export * from "./select"
+50
View File
@@ -0,0 +1,50 @@
import {
FC,
ReactElement,
SelectHTMLAttributes,
} from 'react';
import { cn } from '@imphnen-frontend-service/utils';
type TSelectSize = 'sm' | 'md' | 'lg';
type Width = 'standard' | 'custom';
type TSelectProps = Omit<
SelectHTMLAttributes<HTMLSelectElement>,
'size'
> & {
size?: TSelectSize;
widthform?: Width;
disabled?: boolean;
};
const sizeClasses: Record<TSelectSize, string> = {
sm: 'text-[10px] max-h-[34px]',
md: 'text-[12px] max-h-[36px]',
lg: 'text-[15px] max-h-[38px]',
};
const disabledClass =
'opacity-50 hover:border-neutral-200 cursor-not-allowed';
export const Select: FC<TSelectProps> = ({
size = 'md',
widthform = 'standard',
disabled,
className,
children,
...rest
}): ReactElement => {
const mergedClassName = cn(
`appearance-none px-[12px] py-[8px] text-neutral-800 bg-white placeholder:text-neutral-300 border border-neutral-200 hover:border-blue-300 focus:outline-1 focus:outline-blue-500 rounded-md`,
sizeClasses[size],
widthform === 'standard' && 'min-w-70',
disabled && disabledClass,
className
);
return (
<select className={mergedClassName} disabled={disabled} {...rest}>
{children}
</select>
);
};
+3 -1
View File
@@ -4,4 +4,6 @@ export * from './input-field';
export * from './pagination';
export * from './modal/modal';
export * from './stepper';
export * from './accordion';
export * from './accordion';
export * from './register-mentor-step';
export * from './select-field'
@@ -0,0 +1 @@
export * from './register-mentor-step';
@@ -0,0 +1,53 @@
import { FC, ReactElement } from "react";
type TRegisterMentorStep = {
step: number;
};
const steps = [
"Informasi Personal",
"Detail Mentor",
"Sesi Mentoring & Dokumen Pendukung",
"Informasi Akun Pribadi",
];
export const RegisterMentorStep: FC<TRegisterMentorStep> = ({ step }): ReactElement => {
const progressPercent = ((step - 1) / (steps.length - 1)) * 100;
return (
<div className="relative w-full px-8">
{/* Garis dasar (abu/biru muda) */}
<div className="absolute top-5 left-8 right-8 h-0.5 bg-blue-100 z-0" />
{/* Garis progress biru (dinamis) */}
<div
className="absolute top-5 left-8 h-0.5 bg-blue-500 z-0 transition-all duration-300"
style={{ width: `calc(${progressPercent}% - 0.5rem)` }} // -0.5rem agar tidak overlap ke lingkaran
/>
<div className="flex justify-between relative z-10">
{steps.map((label, index) => {
const currentStep = index + 1;
const isActive = currentStep === step;
return (
<div key={index} className="flex flex-col items-center flex-1 text-center">
{/* Lingkaran angka */}
<div
className={`w-10 h-10 rounded-full flex items-center justify-center border-2 ${
isActive
? "bg-gradient-to-b from-purple-600 to-blue-500 text-white border-transparent"
: "bg-white text-gray-700 border-blue-400"
}`}
>
<span className="font-bold">{currentStep}</span>
</div>
{/* Label */}
<span className="text-xs text-blue-600 mt-2 leading-tight">{label}</span>
</div>
);
})}
</div>
</div>
);
};
@@ -0,0 +1 @@
export * from './select-field'
@@ -0,0 +1,93 @@
import {
FC,
ReactElement,
SelectHTMLAttributes,
DetailedHTMLProps,
} from 'react';
import { Select } from '../../atoms'; // Custom select atom kamu
import { cn } from '@imphnen-frontend-service/utils';
export type TSelectSize = 'sm' | 'md' | 'lg';
export type TSelectFieldProps = Omit<
DetailedHTMLProps<SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>,
'size'
> & {
label: string;
size?: TSelectSize;
error?: string;
helperText?: string;
htmlFor?: string;
disabled?: boolean;
};
const sizeClasses: Record<TSelectSize, { label: string; helperText: string }> = {
lg: {
label: 'text-p3 font-medium',
helperText: 'text-label3 font-normal',
},
md: {
label: 'text-label1 font-medium',
helperText: 'text-label2 font-normal',
},
sm: {
label: 'text-label2 font-medium',
helperText: 'text-label2 font-normal',
},
};
export const SelectField: FC<TSelectFieldProps> = ({
label,
size = 'md',
error,
helperText,
htmlFor,
disabled,
className,
children,
...rest
}): ReactElement => {
return (
<div className="flex flex-col gap-[8px]">
<label
htmlFor={htmlFor}
className={cn(
'items-start justify-item-start text-start !text-neutral-800',
sizeClasses[size].label
)}
>
{label}
</label>
<Select
{...(htmlFor && { id: htmlFor })}
size={size}
disabled={disabled}
className={cn(
error &&
'border-danger-500 hover:border-danger-500 focus:outline-danger-500',
className,
disabled && 'opacity-50 cursor-not-allowed'
)}
{...rest}
>
{children}
</Select>
{error ? (
<p className="text-danger-500 text-label1 text-left">{error}</p>
) : (
helperText && (
<p
className={cn(
'text-label2 text-left',
sizeClasses[size].helperText
)}
>
{helperText}
</p>
)
)}
</div>
);
};
@@ -6,14 +6,14 @@ import { FC, ReactElement } from "react";
function AuthBanner({text, href}: {text: string, href: string}){
return (
<div className='hidden xl:block relative rounded-md'>
<img src="/image/95319c4f9953dfe6180200e529dfcea5.webp" alt="Banner" className='w-[420px] h-[632px] object-[80%] object-cover rounded-lg' />
<img src="/image/95319c4f9953dfe6180200e529dfcea5.webp" alt="Banner" className='w-[420px] min-h-[632px] object-[80%] object-cover rounded-lg' />
<div className='absolute top-0 bg-gradient-to-b from-primary-500 to-transparent w-full rounded-t-lg h-[163px] py-5 px-5'>
<Button variant='secondary' className='gap-2' onClick={() => document.location.href = `${href}`}>
<ArrowLeftOutlined />
<p>{text}</p>
</Button>
</div>
<div className='absolute bottom-0 bg-gradient-to-t from-primary-500 to-transparent w-full rounded-b-lg h-[263px] flex flex-col items-center justify-center'>
<div className='absolute bottom-0 bg-gradient-to-t from-primary-500 to-transparent w-full rounded-b-lg min-h-[263px] flex flex-col items-center justify-center'>
<img src="/image/9261045e09137f3fcb925a78c55b6ddb.webp" alt="Logo" width={317} />
</div>
</div>