All files / components/collections FieldPermissionSelector.tsx

72.72% Statements 16/22
72.22% Branches 13/18
75% Functions 6/8
78.94% Lines 15/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111                                            97x 97x 61x 5x 5x 5x           97x   1x     1x     1x     1x       97x                         1x                                             25x       1x                                            
import React from 'react';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Globe, ListFilter } from 'lucide-react';
import { cn } from '@/lib/utils';
 
interface FieldPermissionSelectorProps {
    label: string;
    description: string;
    value: string;
    fields: string[];
    onChange: (value: string) => void;
}
 
export default function FieldPermissionSelector({
    label,
    description,
    value,
    fields,
    onChange,
}: FieldPermissionSelectorProps) {
    const isAll = value === '*';
    const selectedFields = React.useMemo(() => {
        if (isAll) return [];
        try {
            const parsed = JSON.parse(value);
            return Array.isArray(parsed) ? parsed : [];
        } catch {
            return [];
        }
    }, [value, isAll]);
 
    const handleToggleField = (fieldName: string) => {
        let next: string[];
        Iif (selectedFields.includes(fieldName)) {
            next = selectedFields.filter(f => f !== fieldName);
        } else {
            next = [...selectedFields, fieldName];
        }
 
        Iif (next.length === 0) {
            onChange('*');
        } else {
            onChange(JSON.stringify(next));
        }
    };
 
    return (
        <div className="space-y-3">
            <div>
                <Label className="text-base font-semibold">{label}</Label>
                <p className="text-sm text-muted-foreground">{description}</p>
            </div>
 
            <div className="flex flex-col gap-3 p-4 border rounded-lg bg-card text-card-foreground shadow-sm">
                <div className="flex items-center gap-2">
                    <Button
                        type="button"
                        variant={isAll ? 'default' : 'outline'}
                        size="sm"
                        onClick={() => onChange('*')}
                        className="flex-1 gap-2"
                    >
                        <Globe className="h-4 w-4" />
                        All Fields (*)
                    </Button>
                    <Button
                        type="button"
                        variant={!isAll ? 'default' : 'outline'}
                        size="sm"
                        onClick={() => {
                            if (isAll) onChange('[]');
                        }}
                        className="flex-1 gap-2"
                    >
                        <ListFilter className="h-4 w-4" />
                        Specific Fields
                    </Button>
                </div>
 
                {!isAll && (
                    <div className="grid grid-cols-2 sm:grid-cols-3 gap-3 mt-2 p-3 bg-muted/30 rounded-md border border-dashed">
                        {fields.map((field) => (
                            <div key={field} className="flex items-center space-x-2">
                                <Checkbox
                                    id={`${label}-${field}`}
                                    checked={selectedFields.includes(field)}
                                    onCheckedChange={() => handleToggleField(field)}
                                />
                                <label
                                    htmlFor={`${label}-${field}`}
                                    className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer"
                                >
                                    {field}
                                </label>
                            </div>
                        ))}
                    </div>
                )}
 
                <p className="text-xs text-muted-foreground text-center">
                    {isAll
                        ? "All existing and future fields will be accessible."
                        : `${selectedFields.length} of ${fields.length} fields selected.`}
                </p>
            </div>
        </div>
    );
}