From 7b6c9ac92a7be8ddef22bb695389400c53434662 Mon Sep 17 00:00:00 2001 From: "Kalana B. Thilakarathna" Date: Mon, 19 Oct 2026 22:12:40 +0530 Subject: [PATCH] feat: update row actions to include payment functionality and add corresponding icon --- .../orders/_components/orders-client.tsx | 2 +- distribution_fe/app/globals.css | 42 +++++++++++++ .../components/shared/data-table/types.ts | 3 +- .../components/shared/row-actions.tsx | 2 + .../components/shared/top-loader.tsx | 59 +++++++------------ 5 files changed, 69 insertions(+), 39 deletions(-) diff --git a/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx b/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx index 595080d..30242c5 100644 --- a/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx +++ b/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx @@ -160,7 +160,7 @@ export function OrdersClient() { visible: (target) => target.status === 'Printed', }, { - action: 'edit', + action: 'pay', label: 'Record payment', onClick: handleRecordPayment, visible: (target) => target.paymentStatus !== 'Paid', diff --git a/distribution_fe/app/globals.css b/distribution_fe/app/globals.css index ff09f81..bb6547e 100644 --- a/distribution_fe/app/globals.css +++ b/distribution_fe/app/globals.css @@ -133,4 +133,46 @@ .react-grid-item > .react-resizable-handle::after { border-right-color: var(--muted-foreground); border-bottom-color: var(--muted-foreground); +} + +/* Top loading strip: thin bar sliding across with a neon-red leading dot. */ +.top-loader { + pointer-events: none; + position: absolute; + left: 0; + right: 0; + top: 0; + height: 2px; + overflow: visible; + z-index: 50; +} +.top-loader__bar { + position: absolute; + inset: 0; + background: linear-gradient( + 90deg, + transparent 0%, + rgba(255, 60, 90, 0.35) 55%, + rgba(255, 90, 120, 0.9) 90%, + #ff2e63 100% + ); + transform: translateX(-100%); + animation: top-loader-slide 1.2s cubic-bezier(0.4, 0, 0.2, 1) infinite; +} +.top-loader__head { + position: absolute; + right: -4px; + top: -2px; + height: 6px; + width: 10px; + border-radius: 9999px; + background: #ff6b8a; + box-shadow: + 0 0 6px 1px #ff2e63, + 0 0 14px 2px rgba(255, 46, 99, 0.75), + 0 0 24px 4px rgba(255, 46, 99, 0.35); +} +@keyframes top-loader-slide { + 0% { transform: translateX(-100%); } + 100% { transform: translateX(100%); } } \ No newline at end of file diff --git a/distribution_fe/components/shared/data-table/types.ts b/distribution_fe/components/shared/data-table/types.ts index c49fbd1..ee84db2 100644 --- a/distribution_fe/components/shared/data-table/types.ts +++ b/distribution_fe/components/shared/data-table/types.ts @@ -13,7 +13,8 @@ export type RowActionKind = | 'cancel' | 'print' | 'finalize' - | 'generate'; + | 'generate' + | 'pay'; export interface BadgeConfig { colorMap?: Record; diff --git a/distribution_fe/components/shared/row-actions.tsx b/distribution_fe/components/shared/row-actions.tsx index 77bb20f..6ef3900 100644 --- a/distribution_fe/components/shared/row-actions.tsx +++ b/distribution_fe/components/shared/row-actions.tsx @@ -3,6 +3,7 @@ import * as React from "react" import { HugeiconsIcon } from "@hugeicons/react" import { + AddMoneyCircleIcon, Cancel01Icon, CheckmarkCircle02Icon, CheckmarkSquare01Icon, @@ -24,6 +25,7 @@ const ACTION_ICONS = { edit: PencilEdit01Icon, finalize: CheckmarkSquare01Icon, generate: CheckmarkSquare01Icon, + pay: AddMoneyCircleIcon, print: PrinterIcon, view: EyeIcon, } as const diff --git a/distribution_fe/components/shared/top-loader.tsx b/distribution_fe/components/shared/top-loader.tsx index 140f32d..cda83f6 100644 --- a/distribution_fe/components/shared/top-loader.tsx +++ b/distribution_fe/components/shared/top-loader.tsx @@ -1,44 +1,29 @@ 'use client' -export function TopLoader({ active }: { active: boolean }) { - if (!active) return null +import { useEffect, useState } from 'react' + +/** + * Thin top strip shown while `active` is true. Stays visible for at least + * `minDurationMs` so quick fetches don't produce an invisible flicker. + */ +export function TopLoader({ active, minDurationMs = 350 }: { active: boolean; minDurationMs?: number }) { + const [visible, setVisible] = useState(active) + + useEffect(() => { + if (active) { + setVisible(true) + return + } + const t = setTimeout(() => setVisible(false), minDurationMs) + return () => clearTimeout(t) + }, [active, minDurationMs]) + + if (!visible) return null return ( -
-
- +
+
+
-
) } -- 2.52.0