diff --git a/src/app/globals.css b/src/app/globals.css index 386e7620..79af241b 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,5 +1,6 @@ @import 'tailwindcss'; @plugin "daisyui"; +@import '../styles/daisyui.css'; :root { --color-primary: #1f74bf; diff --git a/src/components/Tooltip.tsx b/src/components/Tooltip.tsx new file mode 100644 index 00000000..02f86dca --- /dev/null +++ b/src/components/Tooltip.tsx @@ -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 ( +
+
+ {content} +
+ + {children} +
+ ); +}; + +export default Tooltip; diff --git a/src/components/pages/ApprovalSteps.tsx b/src/components/pages/ApprovalSteps.tsx new file mode 100644 index 00000000..4022e254 --- /dev/null +++ b/src/components/pages/ApprovalSteps.tsx @@ -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 ( + + {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 ( + + {formatDate(approval.date, 'YYYY-MM-DD')} + Oleh: {approval.action_by} + Catatan: {approval.notes} + + } + > + + + ) + } + > + {approval.role} + + ); + })} + + ); +}; + +export default ApprovalSteps; diff --git a/src/components/steps/StepItem.tsx b/src/components/steps/StepItem.tsx new file mode 100644 index 00000000..85ec4f3e --- /dev/null +++ b/src/components/steps/StepItem.tsx @@ -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 ( +
  • + {icon} + +
    {children}
    +
  • + ); +}; + +export default StepItem; diff --git a/src/components/steps/Steps.tsx b/src/components/steps/Steps.tsx new file mode 100644 index 00000000..29d307e1 --- /dev/null +++ b/src/components/steps/Steps.tsx @@ -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 ( + + ); +}; + +export default Steps; diff --git a/src/styles/daisyui.css b/src/styles/daisyui.css new file mode 100644 index 00000000..9a148fb4 --- /dev/null +++ b/src/styles/daisyui.css @@ -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); + } +} diff --git a/src/types/api/api-general.d.ts b/src/types/api/api-general.d.ts index 6a3fc6be..cf3e57f7 100644 --- a/src/types/api/api-general.d.ts +++ b/src/types/api/api-general.d.ts @@ -66,3 +66,11 @@ export type flags = | 'STARTER' | 'FINISHER' | 'OVK'; + +export type ApprovalsLine = { + action_by?: string; + date?: string; + notes?: string; + role?: string; + status: 'approved' | 'rejected' | 'waiting'; +}[];