| 1 | import { useState } from "react"; |
| 2 | import { |
| 3 | Select, |
| 4 | SelectContent, |
| 5 | SelectItem, |
| 6 | SelectTrigger, |
| 7 | SelectValue, |
| 8 | } from "@/components/ui/select"; |
| 9 | import { Button } from "@/components/ui/button"; |
| 10 | |
| 11 | type BulkAction = "approve" | "deny" | "ban"; |
| 12 | |
| 13 | interface FloatingActionBarProps { |
| 14 | selectedCount: number; |
| 15 | totalCount: number; |
| 16 | isAllSelected: boolean; |
| 17 | onSelectAll: () => void; |
| 18 | onApprove: () => void; |
| 19 | onDeny: () => void; |
| 20 | onBan: () => void; |
| 21 | } |
| 22 | |
| 23 | export const FloatingActionBar = ({ |
| 24 | selectedCount, |
| 25 | totalCount, |
| 26 | isAllSelected, |
| 27 | onSelectAll, |
| 28 | onApprove, |
| 29 | onDeny, |
| 30 | onBan, |
| 31 | }: FloatingActionBarProps) => { |
| 32 | const [selectedAction, setSelectedAction] = useState<BulkAction>("approve"); |
| 33 | |
| 34 | const handleExecute = () => { |
| 35 | switch (selectedAction) { |
| 36 | case "approve": |
| 37 | onApprove(); |
| 38 | break; |
| 39 | case "deny": |
| 40 | onDeny(); |
| 41 | break; |
| 42 | case "ban": |
| 43 | onBan(); |
| 44 | break; |
| 45 | } |
| 46 | }; |
| 47 | |
| 48 | const getExecuteButtonStyle = () => { |
| 49 | switch (selectedAction) { |
| 50 | case "approve": |
| 51 | return "bg-green-600 hover:bg-green-700"; |
| 52 | case "deny": |
| 53 | return "bg-red-600 hover:bg-red-700"; |
| 54 | case "ban": |
| 55 | return "bg-orange-600 hover:bg-orange-700"; |
| 56 | } |
| 57 | }; |
| 58 | |
| 59 | return ( |
| 60 | <div className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 animate-in slide-in-from-bottom-4 fade-in duration-200"> |
| 61 | <div className="flex items-center gap-2 px-3 py-2 bg-background rounded-lg shadow-lg border border-foreground/20"> |
| 62 | <button |
| 63 | onClick={onSelectAll} |
| 64 | className={`px-3 h-10 text-sm font-medium rounded-md transition-colors whitespace-nowrap ${ |
| 65 | isAllSelected |
| 66 | ? "bg-primary text-primary-foreground" |
| 67 | : "bg-secondary text-secondary-foreground hover:bg-secondary/80" |
| 68 | }`} |
| 69 | > |
| 70 | {isAllSelected ? "Deselect" : "Select All"} |
| 71 | </button> |
| 72 | <span className="text-sm font-medium text-foreground whitespace-nowrap px-1"> |
| 73 | {selectedCount}/{totalCount} |
| 74 | </span> |
| 75 | {selectedCount > 0 && ( |
| 76 | <> |
| 77 | <Select |
| 78 | value={selectedAction} |
| 79 | onValueChange={(v) => setSelectedAction(v as BulkAction)} |
| 80 | > |
| 81 | <SelectTrigger className="w-25 h-10"> |
| 82 | <SelectValue /> |
| 83 | </SelectTrigger> |
| 84 | <SelectContent> |
| 85 | <SelectItem value="approve">Approve</SelectItem> |
| 86 | <SelectItem value="deny">Deny</SelectItem> |
| 87 | <SelectItem value="ban">Ban</SelectItem> |
| 88 | </SelectContent> |
| 89 | </Select> |
| 90 | <Button |
| 91 | onClick={handleExecute} |
| 92 | className={`h-10 px-4 text-white ${getExecuteButtonStyle()}`} |
| 93 | > |
| 94 | Run |
| 95 | </Button> |
| 96 | </> |
| 97 | )} |
| 98 | </div> |
| 99 | </div> |
| 100 | ); |
| 101 | }; |