Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 30 additions & 22 deletions app/action/[userId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,25 +164,31 @@ function ContributeFlow({ contribution, onSuccess }: { contribution: MyContribut
);

if (step === 'enter_amount') return (
<div className="flex items-center gap-2 flex-wrap">
<div className="flex flex-col sm:flex-row sm:items-center gap-2 w-full">
<Input type="number" placeholder={`Amount${contribution.minimumAmount ? ` (min ${fmtRwf(Number(contribution.minimumAmount), contribution.currency)})` : ''}`}
value={amount} onChange={(e) => setAmount(e.target.value)} className="h-8 text-xs w-36" autoFocus />
<Button size="sm" variant="outline" className="h-8 text-xs" onClick={cancel}>Cancel</Button>
<Button size="sm" className="h-8 text-xs bg-[#00B512] hover:bg-[#009a0f] text-white" onClick={() => {
if (!amount || Number(amount) <= 0) return;
setStep('enter_pin');
}}>Next</Button>
value={amount} onChange={(e) => setAmount(e.target.value)} className="h-8 text-xs w-full sm:w-36 min-w-0" autoFocus />
<div className="flex gap-2">
<Button size="sm" variant="outline" className="h-8 text-xs flex-1 sm:flex-none" onClick={cancel}>Cancel</Button>
<Button size="sm" className="h-8 text-xs flex-1 sm:flex-none bg-[#00B512] hover:bg-[#009a0f] text-white" onClick={() => {
if (!amount || Number(amount) <= 0) return;
setStep('enter_pin');
}}>Next</Button>
</div>
</div>
);

if (step === 'enter_pin') return (
<div className="flex items-center gap-2 flex-wrap">
<div className="flex items-center gap-1 text-xs text-gray-500"><Lock size={11} /><span>PIN</span></div>
<Input type="password" inputMode="numeric" maxLength={4} placeholder="••••"
value={pin} onChange={(e) => setPin(e.target.value.replace(/\D/g, '').slice(0, 4))}
className="h-8 text-xs w-20 tracking-widest" autoFocus />
<Button size="sm" variant="outline" className="h-8 text-xs" onClick={cancel}>Cancel</Button>
<Button size="sm" className="h-8 text-xs bg-[#00B512] hover:bg-[#009a0f] text-white" onClick={handlePay}>Pay</Button>
<div className="flex flex-col sm:flex-row sm:items-center gap-2 w-full">
<div className="flex items-center gap-2">
<div className="flex items-center gap-1 text-xs text-gray-500"><Lock size={11} /><span>PIN</span></div>
<Input type="password" inputMode="numeric" maxLength={4} placeholder="••••"
value={pin} onChange={(e) => setPin(e.target.value.replace(/\D/g, '').slice(0, 4))}
className="h-8 text-xs w-full sm:w-20 min-w-0 tracking-widest" autoFocus />
</div>
<div className="flex gap-2">
<Button size="sm" variant="outline" className="h-8 text-xs flex-1 sm:flex-none" onClick={cancel}>Cancel</Button>
<Button size="sm" className="h-8 text-xs flex-1 sm:flex-none bg-[#00B512] hover:bg-[#009a0f] text-white" onClick={handlePay}>Pay</Button>
</div>
</div>
);

Expand Down Expand Up @@ -322,7 +328,7 @@ function ContributionCard({ contribution: initial, currentUserId }: { contributi
)}

{c.isAdmin && (isActive || c.status === 'expired') && (
<div className="flex gap-2 ml-auto">
<div className="flex gap-2 flex-shrink-0 ml-auto">
{isActive && (
<Button variant="outline" size="sm" className="h-7 text-[11px] border-red-200 text-red-500 hover:bg-red-50" onClick={handleClose}>
Close
Expand All @@ -337,11 +343,13 @@ function ContributionCard({ contribution: initial, currentUserId }: { contributi
</div>

{extendOpen && (
<div className="mt-3 flex items-center gap-2 flex-wrap">
<div className="mt-3 flex flex-col sm:flex-row sm:items-center gap-2">
<Input type="date" min={new Date().toISOString().split('T')[0]} value={newDeadline}
onChange={(e) => setNewDeadline(e.target.value)} className="h-8 text-xs w-44" />
<Button size="sm" className="h-8 text-xs bg-[#00B512] hover:bg-[#009a0f] text-white" onClick={handleExtend}>Save</Button>
<Button size="sm" variant="outline" className="h-8 text-xs" onClick={() => { setExtendOpen(false); setNewDeadline(''); }}>Cancel</Button>
onChange={(e) => setNewDeadline(e.target.value)} className="h-8 text-xs w-full sm:w-44 min-w-0" />
<div className="flex gap-2">
<Button size="sm" className="h-8 text-xs flex-1 sm:flex-none bg-[#00B512] hover:bg-[#009a0f] text-white" onClick={handleExtend}>Save</Button>
<Button size="sm" variant="outline" className="h-8 text-xs flex-1 sm:flex-none" onClick={() => { setExtendOpen(false); setNewDeadline(''); }}>Cancel</Button>
</div>
</div>
)}

Expand Down Expand Up @@ -1414,10 +1422,10 @@ const ActionsByAccountPage = () => {
<div className="space-y-4">
{/* Tab switcher — only show when not viewing another user */}
{!isViewingAnotherUser && (
<div className="flex gap-2">
<div className="flex flex-wrap gap-2">
<button
onClick={() => setIndividualTab('actions')}
className={`px-5 py-2 rounded-full text-sm font-semibold transition-colors ${
className={`flex-1 sm:flex-none justify-center px-5 py-2 rounded-full text-sm font-semibold transition-colors ${
individualTab === 'actions'
? 'bg-[#00B512] text-white shadow'
: 'border border-gray-200 dark:border-darkBorder-light dark:bg-darkBg-interactive dark:text-white text-[#00313A] hover:bg-gray-50 dark:hover:bg-darkBg-card'
Expand All @@ -1427,7 +1435,7 @@ const ActionsByAccountPage = () => {
</button>
<button
onClick={() => setIndividualTab('contributions')}
className={`inline-flex items-center gap-2 px-5 py-2 rounded-full text-sm font-semibold transition-colors ${
className={`flex-1 sm:flex-none inline-flex items-center justify-center gap-2 px-5 py-2 rounded-full text-sm font-semibold transition-colors ${
individualTab === 'contributions'
? 'bg-[#00B512] text-white shadow'
: 'border border-gray-200 dark:border-darkBorder-light dark:bg-darkBg-interactive dark:text-white text-[#00313A] hover:bg-gray-50 dark:hover:bg-darkBg-card'
Expand Down
61 changes: 36 additions & 25 deletions app/groups/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,27 +213,29 @@ function GroupRow({

<td className="px-4 py-3 text-right">
<div
className="flex items-center justify-end gap-1 opacity-0 group-hover:opacity-100 transition-opacity"
className="flex items-center justify-end gap-1"
onClick={(e) => e.stopPropagation()}
>
<Button
variant="ghost"
size="icon"
className="h-8 w-8 text-gray-500 dark:text-gray-400 hover:text-brand-green dark:hover:text-brand-gold hover:bg-brand-green/10 dark:hover:bg-brand-gold/10"
title="Open chat"
onClick={onChat}
>
<MessageSquare className="h-4 w-4" />
</Button>
<Button
variant="ghost"
size="icon"
className="h-8 w-8 text-gray-500 dark:text-gray-400 hover:text-brand-green dark:hover:text-brand-gold hover:bg-brand-green/10 dark:hover:bg-brand-gold/10"
title="Contributions"
onClick={onContributions}
>
<Target className="h-4 w-4" />
</Button>
<div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
<Button
variant="ghost"
size="icon"
className="h-8 w-8 text-gray-500 dark:text-gray-400 hover:text-brand-green dark:hover:text-brand-gold hover:bg-brand-green/10 dark:hover:bg-brand-gold/10"
title="Open chat"
onClick={onChat}
>
<MessageSquare className="h-4 w-4" />
</Button>
<Button
variant="ghost"
size="icon"
className="h-8 w-8 text-gray-500 dark:text-gray-400 hover:text-brand-green dark:hover:text-brand-gold hover:bg-brand-green/10 dark:hover:bg-brand-gold/10"
title="Contributions"
onClick={onContributions}
>
<Target className="h-4 w-4" />
</Button>
</div>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
Expand Down Expand Up @@ -422,12 +424,21 @@ function GroupDetailsPanel({
<div
ref={panelRef}
className={cn(
"fixed inset-y-0 right-0 w-96 max-w-[95vw] bg-white dark:bg-darkBg-card shadow-2xl transform transition-transform duration-300 ease-in-out z-[110] border-l border-gray-200 dark:border-darkBorder-light flex flex-col",
isOpen ? "translate-x-0" : "translate-x-full"
"fixed bg-white dark:bg-darkBg-card shadow-2xl transform transition-transform duration-300 ease-in-out z-[110] flex flex-col",
"bottom-0 inset-x-0 h-[90vh] rounded-t-2xl border-t border-gray-200 dark:border-darkBorder-light",
"sm:inset-y-0 sm:right-0 sm:inset-x-auto sm:w-96 sm:h-full sm:rounded-none sm:border-t-0 sm:border-l sm:border-gray-200 sm:dark:border-darkBorder-light",
isOpen
? "translate-y-0 sm:translate-y-0 sm:translate-x-0"
: "translate-y-full sm:translate-y-0 sm:translate-x-full"
)}
>
{/* Mobile drag handle */}
<div className="sm:hidden flex justify-center pt-2.5 pb-1 flex-shrink-0">
<div className="w-10 h-1 bg-gray-300 dark:bg-gray-600 rounded-full" />
</div>

{/* Header */}
<div className="flex items-center justify-between px-6 py-4 border-b border-gray-100 dark:border-darkBorder-light flex-shrink-0">
<div className="flex items-center justify-between px-4 sm:px-6 py-3 sm:py-4 border-b border-gray-100 dark:border-darkBorder-light flex-shrink-0">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">Group Details</h2>
<div className="flex items-center gap-1">
<Button
Expand All @@ -453,7 +464,7 @@ function GroupDetailsPanel({
</div>

{/* Content */}
<div className="flex-1 overflow-y-auto px-5 pb-6">
<div className="flex-1 overflow-y-auto px-4 sm:px-5 pb-6">
<GroupDetailsContent
groupId={groupId}
token={token}
Expand Down Expand Up @@ -563,7 +574,7 @@ export default function GroupsPage() {

<div className="flex-1 flex flex-col overflow-hidden px-4 sm:px-6 lg:px-8 pb-4">
{/* Page header */}
<div className="flex items-start justify-between mb-6">
<div className="flex flex-col sm:flex-row sm:items-start justify-between gap-3 mb-6">
<div>
<BackButton className="mb-3" />
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Groups</h1>
Expand All @@ -572,7 +583,7 @@ export default function GroupsPage() {
</p>
</div>

<div className="flex items-center gap-2 sm:gap-3 mt-1">
<div className="flex items-center gap-2 sm:gap-3 sm:mt-1 self-start sm:self-auto">
{/* Expandable search */}
<div className={cn(
"flex items-center transition-all duration-300 overflow-hidden",
Expand Down
22 changes: 14 additions & 8 deletions components/ActionPage/ActionPageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,8 @@ const ActionPageLayout: React.FC = () => {
title: "Actions",
key: "action",
align: "center",
fixed: "right" as const,
width: 160,
render: (_, record) => (
<div className="flex items-center justify-center gap-2">
<Button
Expand Down Expand Up @@ -366,13 +368,13 @@ const ActionPageLayout: React.FC = () => {
<p className="text-sm text-gray-600">Design QR-powered experiences and manage them in one place.</p>
</div>
<div className="flex gap-3">
<Button icon={<ReloadOutlined />} onClick={fetchActions}>
<Button icon={<ReloadOutlined />} onClick={fetchActions} className="w-full sm:w-auto">
Refresh
</Button>
<Button
type="primary"
icon={<PlusOutlined />}
className="bg-[#00B512] border-none hover:bg-[#009e10]"
className="w-full sm:w-auto bg-[#00B512] border-none hover:bg-[#009e10]"
onClick={() => setWizardOpen(true)}
>
New Action
Expand All @@ -391,6 +393,7 @@ const ActionPageLayout: React.FC = () => {
<Tabs
activeKey={activeTab}
onChange={(key) => setActiveTab(key as FilterTab)}
tabBarStyle={{ overflowX: 'auto', whiteSpace: 'nowrap' }}
items={[
{
key: 'active',
Expand All @@ -406,25 +409,26 @@ const ActionPageLayout: React.FC = () => {
/>
</div>

<div className="flex-1 overflow-auto">
<div className="flex-1 overflow-hidden rounded-2xl border border-gray-100">
<Table
loading={loading}
dataSource={tableData}
columns={columns}
scroll={{ x: 800 }}
pagination={{ pageSize: 6, showSizeChanger: false }}
rowSelection={{ type: 'checkbox' }}
locale={{
emptyText: (
<Empty
<Empty
description={
activeTab === 'archive'
? "No archived or expired actions yet."
activeTab === 'archive'
? "No archived or expired actions yet."
: "No actions yet. Create your first one to get started."
}
}
/>
),
}}
className="border border-gray-100 rounded-2xl"
className="rounded-2xl"
/>
</div>

Expand All @@ -445,6 +449,8 @@ const ActionPageLayout: React.FC = () => {
okText="Transfer"
confirmLoading={transferSubmitting}
okButtonProps={{ className: 'bg-[#00B512] border-none hover:bg-[#009e10]' }}
width="min(480px, calc(100vw - 32px))"
style={{ top: 'auto' }}
destroyOnClose
>
<div className="space-y-4 pt-2">
Expand Down
Loading
Loading