Skip to content

Commit 180f300

Browse files
authored
Merge pull request #40 from RayLabsHQ/mobile-layout
Mobile layout Optimised
2 parents 6155e39 + 472f67a commit 180f300

28 files changed

+2475
-918
lines changed

bun.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"tw-animate-css": "^1.3.5",
5252
"typescript": "^5.8.3",
5353
"uuid": "^11.1.0",
54+
"vaul": "^1.1.2",
5455
"zod": "^3.25.75",
5556
},
5657
"devDependencies": {
@@ -1453,6 +1454,8 @@
14531454

14541455
"uuid": ["[email protected]", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
14551456

1457+
"vaul": ["[email protected]", "", { "dependencies": { "@radix-ui/react-dialog": "^1.1.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA=="],
1458+
14561459
"vfile": ["[email protected]", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
14571460

14581461
"vfile-location": ["[email protected]", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"tw-animate-css": "^1.3.5",
7979
"typescript": "^5.8.3",
8080
"uuid": "^11.1.0",
81+
"vaul": "^1.1.2",
8182
"zod": "^3.25.75"
8283
},
8384
"devDependencies": {

src/components/activity/ActivityList.tsx

Lines changed: 113 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@ import { useVirtualizer } from '@tanstack/react-virtual';
33
import type { MirrorJob } from '@/lib/db/schema';
44
import Fuse from 'fuse.js';
55
import { Button } from '../ui/button';
6-
import { RefreshCw } from 'lucide-react';
6+
import { RefreshCw, Check, X, Loader2, Import } from 'lucide-react';
77
import { Card } from '../ui/card';
88
import { formatDate, getStatusColor } from '@/lib/utils';
99
import { Skeleton } from '../ui/skeleton';
1010
import type { FilterParams } from '@/types/filter';
11+
import {
12+
Tooltip,
13+
TooltipContent,
14+
TooltipProvider,
15+
TooltipTrigger,
16+
} from '../ui/tooltip';
1117

1218
type MirrorJobWithKey = MirrorJob & { _rowKey: string };
1319

@@ -73,7 +79,7 @@ export default function ActivityList({
7379
count: filteredActivities.length,
7480
getScrollElement: () => parentRef.current,
7581
estimateSize: (idx) =>
76-
expandedItems.has(filteredActivities[idx]._rowKey) ? 217 : 120,
82+
expandedItems.has(filteredActivities[idx]._rowKey) ? 217 : 100,
7783
overscan: 5,
7884
measureElement: (el) => el.getBoundingClientRect().height + 8,
7985
});
@@ -155,34 +161,121 @@ export default function ActivityList({
155161
}}
156162
className='border-b px-4 pt-4'
157163
>
158-
<div className='flex items-start gap-4'>
159-
<div className='relative mt-2'>
164+
<div className='flex items-start gap-3 sm:gap-4'>
165+
<div className='relative mt-2 flex-shrink-0'>
160166
<div
161167
className={`h-2 w-2 rounded-full ${getStatusColor(
162168
activity.status,
163169
)}`}
164170
/>
165171
</div>
166172

167-
<div className='flex-1'>
168-
<div className='mb-1 flex flex-col sm:flex-row sm:items-center sm:justify-between'>
169-
<p className='font-medium'>{activity.message}</p>
170-
<p className='text-sm text-muted-foreground'>
173+
<div className='flex-1 min-w-0'>
174+
<div className='mb-1 flex items-start justify-between gap-2'>
175+
<div className='flex-1 min-w-0'>
176+
{/* Mobile: Show simplified status-based message */}
177+
<div className='block sm:hidden'>
178+
<p className='font-medium flex items-center gap-1.5'>
179+
{activity.status === 'synced' ? (
180+
<>
181+
<Check className='h-4 w-4 text-teal-600 dark:text-teal-400' />
182+
<span className='text-teal-600 dark:text-teal-400'>Sync successful</span>
183+
</>
184+
) : activity.status === 'mirrored' ? (
185+
<>
186+
<Check className='h-4 w-4 text-emerald-600 dark:text-emerald-400' />
187+
<span className='text-emerald-600 dark:text-emerald-400'>Mirror successful</span>
188+
</>
189+
) : activity.status === 'failed' ? (
190+
<>
191+
<X className='h-4 w-4 text-rose-600 dark:text-rose-400' />
192+
<span className='text-rose-600 dark:text-rose-400'>Operation failed</span>
193+
</>
194+
) : activity.status === 'syncing' ? (
195+
<>
196+
<Loader2 className='h-4 w-4 text-indigo-600 dark:text-indigo-400 animate-spin' />
197+
<span className='text-indigo-600 dark:text-indigo-400'>Syncing in progress</span>
198+
</>
199+
) : activity.status === 'mirroring' ? (
200+
<>
201+
<Loader2 className='h-4 w-4 text-yellow-600 dark:text-yellow-400 animate-spin' />
202+
<span className='text-yellow-600 dark:text-yellow-400'>Mirroring in progress</span>
203+
</>
204+
) : activity.status === 'imported' ? (
205+
<>
206+
<Import className='h-4 w-4 text-blue-600 dark:text-blue-400' />
207+
<span className='text-blue-600 dark:text-blue-400'>Imported</span>
208+
</>
209+
) : (
210+
<span>{activity.message}</span>
211+
)}
212+
</p>
213+
</div>
214+
{/* Desktop: Show status with icon and full message in tooltip */}
215+
<div className='hidden sm:block'>
216+
<TooltipProvider>
217+
<Tooltip>
218+
<TooltipTrigger asChild>
219+
<p className='font-medium flex items-center gap-1.5 cursor-help'>
220+
{activity.status === 'synced' ? (
221+
<>
222+
<Check className='h-4 w-4 text-teal-600 dark:text-teal-400 flex-shrink-0' />
223+
<span className='text-teal-600 dark:text-teal-400'>Sync successful</span>
224+
</>
225+
) : activity.status === 'mirrored' ? (
226+
<>
227+
<Check className='h-4 w-4 text-emerald-600 dark:text-emerald-400 flex-shrink-0' />
228+
<span className='text-emerald-600 dark:text-emerald-400'>Mirror successful</span>
229+
</>
230+
) : activity.status === 'failed' ? (
231+
<>
232+
<X className='h-4 w-4 text-rose-600 dark:text-rose-400 flex-shrink-0' />
233+
<span className='text-rose-600 dark:text-rose-400'>Operation failed</span>
234+
</>
235+
) : activity.status === 'syncing' ? (
236+
<>
237+
<Loader2 className='h-4 w-4 text-indigo-600 dark:text-indigo-400 animate-spin flex-shrink-0' />
238+
<span className='text-indigo-600 dark:text-indigo-400'>Syncing in progress</span>
239+
</>
240+
) : activity.status === 'mirroring' ? (
241+
<>
242+
<Loader2 className='h-4 w-4 text-yellow-600 dark:text-yellow-400 animate-spin flex-shrink-0' />
243+
<span className='text-yellow-600 dark:text-yellow-400'>Mirroring in progress</span>
244+
</>
245+
) : activity.status === 'imported' ? (
246+
<>
247+
<Import className='h-4 w-4 text-blue-600 dark:text-blue-400 flex-shrink-0' />
248+
<span className='text-blue-600 dark:text-blue-400'>Imported</span>
249+
</>
250+
) : (
251+
<span className='truncate'>{activity.message}</span>
252+
)}
253+
</p>
254+
</TooltipTrigger>
255+
<TooltipContent side="bottom" align="start" className="max-w-[400px]">
256+
<p className="whitespace-pre-wrap break-words">{activity.message}</p>
257+
</TooltipContent>
258+
</Tooltip>
259+
</TooltipProvider>
260+
</div>
261+
</div>
262+
<p className='text-sm text-muted-foreground whitespace-nowrap flex-shrink-0 ml-2'>
171263
{formatDate(activity.timestamp)}
172264
</p>
173265
</div>
174266

175-
{activity.repositoryName && (
176-
<p className='mb-2 text-sm text-muted-foreground'>
177-
Repository: {activity.repositoryName}
178-
</p>
179-
)}
180-
181-
{activity.organizationName && (
182-
<p className='mb-2 text-sm text-muted-foreground'>
183-
Organization: {activity.organizationName}
184-
</p>
185-
)}
267+
<div className='flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-3'>
268+
{activity.repositoryName && (
269+
<p className='text-sm text-muted-foreground truncate'>
270+
<span className='font-medium'>Repo:</span> {activity.repositoryName}
271+
</p>
272+
)}
273+
{activity.organizationName && (
274+
<p className='text-sm text-muted-foreground truncate'>
275+
<span className='font-medium'>Org:</span> {activity.organizationName}
276+
</p>
277+
)}
278+
</div>
186279

187280
{activity.details && (
188281
<div className='mt-2'>
@@ -199,7 +292,7 @@ export default function ActivityList({
199292
})
200293
}
201294
>
202-
{isExpanded ? 'Hide Details' : 'Show Details'}
295+
{isExpanded ? 'Hide Details' : activity.status === 'failed' ? 'Show Error Details' : 'Show Details'}
203296
</Button>
204297

205298
{isExpanded && (

0 commit comments

Comments
 (0)