mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-25 08:11:12 -05:00
feat: Implement reusable button components
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import {
|
||||
CheckCircle, XCircle, RefreshCw, AlertCircle, Lock, Trash2,
|
||||
Edit, Info, ExternalLink, ChevronDown, ListTree, Calendar
|
||||
AlertCircle, Edit, Info, ExternalLink, ChevronDown, ListTree, Calendar
|
||||
} from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ActionButton } from '@/components/ui/action-button';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
||||
@@ -159,24 +159,14 @@ export const QueueItemActions = memo(({
|
||||
<AlertDescription className="text-blue-800 dark:text-blue-200">
|
||||
<div className="flex items-center justify-between mt-2">
|
||||
<span className="text-sm">Claim this submission to lock it for 15 minutes while you review</span>
|
||||
<Button
|
||||
<ActionButton
|
||||
action="claim"
|
||||
onClick={onClaim}
|
||||
disabled={queueIsLoading || isClaiming}
|
||||
isLoading={isClaiming}
|
||||
size="sm"
|
||||
className="ml-4"
|
||||
>
|
||||
{isClaiming ? (
|
||||
<>
|
||||
<RefreshCw className="w-4 h-4 mr-2 animate-spin" />
|
||||
Claiming...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Lock className="w-4 h-4 mr-2" />
|
||||
Claim Submission
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
/>
|
||||
</div>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
@@ -274,46 +264,29 @@ export const QueueItemActions = memo(({
|
||||
</>
|
||||
)}
|
||||
|
||||
<Button
|
||||
<ActionButton
|
||||
action="approve"
|
||||
onClick={handleApprove}
|
||||
disabled={actionLoading === item.id || isLockedByOther || currentLockSubmissionId !== item.id}
|
||||
className={`flex-1 ${isMobile ? 'h-11' : ''}`}
|
||||
isLoading={actionLoading === item.id}
|
||||
loadingText={
|
||||
item.submission_items && item.submission_items.length > 5
|
||||
? `Processing ${item.submission_items.length} items...`
|
||||
: 'Processing...'
|
||||
}
|
||||
className="flex-1"
|
||||
size={isMobile ? "default" : "default"}
|
||||
>
|
||||
{actionLoading === item.id ? (
|
||||
<>
|
||||
<RefreshCw className={`${isMobile ? "w-5 h-5" : "w-4 h-4"} mr-2 animate-spin`} />
|
||||
{item.submission_items && item.submission_items.length > 5
|
||||
? `Processing ${item.submission_items.length} items...`
|
||||
: 'Processing...'
|
||||
}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CheckCircle className={isMobile ? "w-5 h-5 mr-2" : "w-4 h-4 mr-2"} />
|
||||
Approve
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
<ActionButton
|
||||
action="reject"
|
||||
onClick={handleReject}
|
||||
disabled={actionLoading === item.id || isLockedByOther || currentLockSubmissionId !== item.id}
|
||||
className={`flex-1 ${isMobile ? 'h-11' : ''}`}
|
||||
isLoading={actionLoading === item.id}
|
||||
className="flex-1"
|
||||
size={isMobile ? "default" : "default"}
|
||||
>
|
||||
{actionLoading === item.id ? (
|
||||
<>
|
||||
<RefreshCw className={`${isMobile ? "w-5 h-5" : "w-4 h-4"} mr-2 animate-spin`} />
|
||||
Processing...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<XCircle className={isMobile ? "w-5 h-5 mr-2" : "w-4 h-4 mr-2"} />
|
||||
Reject
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@@ -329,15 +302,13 @@ export const QueueItemActions = memo(({
|
||||
<p className="text-xs mt-1">You can reset it to pending to re-review and approve it.</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
<ActionButton
|
||||
action="reset"
|
||||
onClick={handleResetToPending}
|
||||
disabled={actionLoading === item.id}
|
||||
variant="outline"
|
||||
isLoading={actionLoading === item.id}
|
||||
className="w-full"
|
||||
>
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
Reset to Pending
|
||||
</Button>
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -361,23 +332,22 @@ export const QueueItemActions = memo(({
|
||||
<ListTree className="w-4 h-4 mr-2" />
|
||||
Review Items
|
||||
</Button>
|
||||
<Button
|
||||
<ActionButton
|
||||
action="reset"
|
||||
onClick={handleResetToPending}
|
||||
disabled={actionLoading === item.id}
|
||||
variant="outline"
|
||||
isLoading={actionLoading === item.id}
|
||||
className="flex-1"
|
||||
>
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
Reset All
|
||||
</Button>
|
||||
<Button
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
action="retry"
|
||||
onClick={handleRetryFailed}
|
||||
disabled={actionLoading === item.id}
|
||||
className="flex-1 bg-yellow-600 hover:bg-yellow-700"
|
||||
>
|
||||
<RefreshCw className="w-4 h-4 mr-2" />
|
||||
Retry Failed
|
||||
</Button>
|
||||
isLoading={actionLoading === item.id}
|
||||
className="flex-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -461,27 +431,30 @@ export const QueueItemActions = memo(({
|
||||
/>
|
||||
<div className={`flex gap-2 ${isMobile ? 'flex-col' : ''}`}>
|
||||
{item.status === 'approved' && (
|
||||
<Button
|
||||
variant="destructive"
|
||||
<ActionButton
|
||||
action="reject"
|
||||
onClick={handleReverseReject}
|
||||
disabled={actionLoading === item.id}
|
||||
className={`flex-1 ${isMobile ? 'h-11' : ''}`}
|
||||
isLoading={actionLoading === item.id}
|
||||
className="flex-1"
|
||||
size={isMobile ? "default" : "default"}
|
||||
isMobile={isMobile}
|
||||
>
|
||||
<XCircle className={isMobile ? "w-5 h-5 mr-2" : "w-4 h-4 mr-2"} />
|
||||
Change to Rejected
|
||||
</Button>
|
||||
</ActionButton>
|
||||
)}
|
||||
{item.status === 'rejected' && (
|
||||
<Button
|
||||
<ActionButton
|
||||
action="approve"
|
||||
onClick={handleReverseApprove}
|
||||
disabled={actionLoading === item.id}
|
||||
className={`flex-1 ${isMobile ? 'h-11' : ''}`}
|
||||
isLoading={actionLoading === item.id}
|
||||
className="flex-1"
|
||||
size={isMobile ? "default" : "default"}
|
||||
isMobile={isMobile}
|
||||
>
|
||||
<CheckCircle className={isMobile ? "w-5 h-5 mr-2" : "w-4 h-4 mr-2"} />
|
||||
Change to Approved
|
||||
</Button>
|
||||
</ActionButton>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -491,16 +464,17 @@ export const QueueItemActions = memo(({
|
||||
{/* Delete button for rejected submissions (admin/superadmin only) */}
|
||||
{item.status === 'rejected' && item.type === 'content_submission' && (isAdmin || isSuperuser) && (
|
||||
<div className="pt-2">
|
||||
<Button
|
||||
variant="destructive"
|
||||
<ActionButton
|
||||
action="delete"
|
||||
onClick={handleDeleteSubmission}
|
||||
disabled={actionLoading === item.id}
|
||||
className={`w-full ${isMobile ? 'h-11' : ''}`}
|
||||
isLoading={actionLoading === item.id}
|
||||
className="w-full"
|
||||
size={isMobile ? "default" : "default"}
|
||||
isMobile={isMobile}
|
||||
>
|
||||
<Trash2 className={isMobile ? "w-5 h-5 mr-2" : "w-4 h-4 mr-2"} />
|
||||
Delete Submission
|
||||
</Button>
|
||||
</ActionButton>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user