mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 15:25:46 +00:00
Merge branch 'feat/FE/US-82/TASK-91-slicing-approval-steps-component' into 'feat/FE/US-82/approval-workflow-steps-component'
[FEAT/FE][US#82/TASK#91] Slicing Approval Steps component See merge request mbugroup/lti-web-client!11
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
@import 'tailwindcss';
|
@import 'tailwindcss';
|
||||||
@plugin "daisyui";
|
@plugin "daisyui";
|
||||||
|
@import '../styles/daisyui.css';
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--color-primary: #1f74bf;
|
--color-primary: #1f74bf;
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
import { cn } from '@/lib/helper';
|
||||||
|
import { Color } from '@/types/theme';
|
||||||
|
|
||||||
|
interface TooltipProps {
|
||||||
|
children?: ReactNode;
|
||||||
|
content?: ReactNode;
|
||||||
|
className?: {
|
||||||
|
wrapper?: string;
|
||||||
|
content?: string;
|
||||||
|
};
|
||||||
|
open?: boolean;
|
||||||
|
color?: Color;
|
||||||
|
position?: 'top' | 'bottom' | 'left' | 'right';
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tooltip = ({
|
||||||
|
children,
|
||||||
|
content,
|
||||||
|
className,
|
||||||
|
open,
|
||||||
|
color,
|
||||||
|
position,
|
||||||
|
}: TooltipProps) => {
|
||||||
|
const tooltipBaseClassName = cn('tooltip', {
|
||||||
|
'tooltip-open': typeof open === 'boolean' && open,
|
||||||
|
|
||||||
|
'tooltip-top': position === 'top',
|
||||||
|
'tooltip-bottom': position === 'bottom',
|
||||||
|
'tooltip-left': position === 'left',
|
||||||
|
'tooltip-right': position === 'right',
|
||||||
|
|
||||||
|
'tooltip-primary': color === 'primary',
|
||||||
|
'tooltip-secondary': color === 'secondary',
|
||||||
|
'tooltip-accent': color === 'accent',
|
||||||
|
'tooltip-neutral': color === 'neutral',
|
||||||
|
'tooltip-info': color === 'info',
|
||||||
|
'tooltip-success': color === 'success',
|
||||||
|
'tooltip-warning': color === 'warning',
|
||||||
|
'tooltip-error': color === 'error',
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div className={cn(tooltipBaseClassName, className?.wrapper)}>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
'tooltip-content',
|
||||||
|
'max-w-60 sm:max-w-xs',
|
||||||
|
className?.content
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tooltip;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { Icon } from '@iconify/react';
|
||||||
|
import Steps from '@/components/steps/Steps';
|
||||||
|
import StepItem from '@/components/steps/StepItem';
|
||||||
|
import Tooltip from '@/components/Tooltip';
|
||||||
|
|
||||||
|
import { formatDate } from '@/lib/helper';
|
||||||
|
import { ApprovalsLine } from '@/types/api/api-general';
|
||||||
|
|
||||||
|
interface ApprovalStepsProps {
|
||||||
|
approvals: ApprovalsLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ApprovalSteps = ({ approvals }: ApprovalStepsProps) => {
|
||||||
|
return (
|
||||||
|
<Steps direction='vertical' className='w-full md:steps-horizontal'>
|
||||||
|
{approvals.map((approval, idx) => {
|
||||||
|
const stepItemColor =
|
||||||
|
approval.status === 'approved'
|
||||||
|
? 'success'
|
||||||
|
: approval.status === 'rejected'
|
||||||
|
? 'error'
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const stepItemIcon =
|
||||||
|
approval.status === 'approved'
|
||||||
|
? 'material-symbols:check-rounded'
|
||||||
|
: approval.status === 'rejected'
|
||||||
|
? 'material-symbols:close-rounded'
|
||||||
|
: 'bxs:hourglass';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StepItem
|
||||||
|
key={idx}
|
||||||
|
color={stepItemColor}
|
||||||
|
icon={
|
||||||
|
approval.status !== 'waiting' && (
|
||||||
|
<Tooltip
|
||||||
|
color={stepItemColor}
|
||||||
|
position='right'
|
||||||
|
className={{
|
||||||
|
wrapper: 'md:tooltip-bottom',
|
||||||
|
}}
|
||||||
|
content={
|
||||||
|
<div className='flex flex-col text-base'>
|
||||||
|
<span>{formatDate(approval.date, 'YYYY-MM-DD')}</span>
|
||||||
|
<span>Oleh: {approval.action_by}</span>
|
||||||
|
<span>Catatan: {approval.notes}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Icon icon={stepItemIcon} width={24} height={24} />
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{approval.role}
|
||||||
|
</StepItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Steps>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ApprovalSteps;
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
import { cn } from '@/lib/helper';
|
||||||
|
import { Color } from '@/types/theme';
|
||||||
|
|
||||||
|
interface StepItemProps {
|
||||||
|
children?: ReactNode;
|
||||||
|
icon?: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
color?: Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StepItem = ({ children, icon, className, color }: StepItemProps) => {
|
||||||
|
const stepItemBaseClassName = cn('step', {
|
||||||
|
'step-primary': color === 'primary',
|
||||||
|
'step-secondary': color === 'secondary',
|
||||||
|
'step-accent': color === 'accent',
|
||||||
|
'step-neutral': color === 'neutral',
|
||||||
|
'step-info': color === 'info',
|
||||||
|
'step-success': color === 'success',
|
||||||
|
'step-warning': color === 'warning',
|
||||||
|
'step-error': color === 'error',
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li className={cn(stepItemBaseClassName, className)}>
|
||||||
|
<span className='step-icon'>{icon}</span>
|
||||||
|
|
||||||
|
<div>{children}</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StepItem;
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
|
import { cn } from '@/lib/helper';
|
||||||
|
|
||||||
|
interface StepsProps {
|
||||||
|
children?: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
direction?: 'horizontal' | 'vertical';
|
||||||
|
}
|
||||||
|
|
||||||
|
const Steps = ({ children, className, direction }: StepsProps) => {
|
||||||
|
const stepsBaseClassName = cn('steps gap-2', {
|
||||||
|
'steps-horizontal': direction === 'horizontal',
|
||||||
|
'steps-vertical': direction === 'vertical',
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul className={cn(stepsBaseClassName, 'overflow-visible!', className)}>
|
||||||
|
{children}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Steps;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
@layer utilities {
|
||||||
|
.step.step-success::before {
|
||||||
|
--step-bg: var(--color-success);
|
||||||
|
--step-fg: var(--color-success-content);
|
||||||
|
}
|
||||||
|
|
||||||
|
.step.step-error::before {
|
||||||
|
--step-bg: var(--color-error);
|
||||||
|
--step-fg: var(--color-error-content);
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+8
@@ -66,3 +66,11 @@ export type flags =
|
|||||||
| 'STARTER'
|
| 'STARTER'
|
||||||
| 'FINISHER'
|
| 'FINISHER'
|
||||||
| 'OVK';
|
| 'OVK';
|
||||||
|
|
||||||
|
export type ApprovalsLine = {
|
||||||
|
action_by?: string;
|
||||||
|
date?: string;
|
||||||
|
notes?: string;
|
||||||
|
role?: string;
|
||||||
|
status: 'approved' | 'rejected' | 'waiting';
|
||||||
|
}[];
|
||||||
|
|||||||
Reference in New Issue
Block a user