# All files / src/components CommitDialog.tsx

95.45% Statements 21/22
73.33% Branches 11/15
100% Functions 7/7
100% Lines 19/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

    53x
    53x

    53x
    20x
    9x
    9x

    53x
    2x
    2x
    2x

    53x
    2x
    1x
    1x
    1x
    1x

    53x
    1x

    4x

     import { useState, useEffect, useRef } from 'react'
    import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'
    import { Button } from '@/components/ui/button'
    import { Badge } from '@/components/ui/badge'

    interface CommitDialogProps {
      open: boolean
      modifiedCount: number
      onCommit: (message: string) => void
      onClose: () => void
    }

    export function CommitDialog({ open, modifiedCount, onCommit, onClose }: CommitDialogProps) {
      const [message, setMessage] = useState('')
      const inputRef = useRef<HTMLTextAreaElement>(null)

      useEffect(() => {
        if (open) {
          setMessage('') // eslint-disable-line react-hooks/set-state-in-effect -- reset on dialog open
          setTimeout(() => inputRef.current?.focus(), 50)
        }
      }, [open])

      const handleSubmit = () => {
        const trimmed = message.trim()
        Iif (!trimmed) return
        onCommit(trimmed)
      }

      const handleKeyDown = (e: React.KeyboardEvent) => {
        if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
          e.preventDefault()
          handleSubmit()
        E} else if (e.key === 'Escape') {
          onClose()
        }
      }

      return (
        <Dialog open={open} onOpenChange={(isOpen) => { Eif (!isOpen) onClose() }}>
          <DialogContent showCloseButton={false} className="sm:max-w-[420px]">
            <DialogHeader>
              <div className="flex items-center justify-between">
                <DialogTitle>Commit & Push</DialogTitle>
                <Badge variant="secondary" className="text-xs">
                  {modifiedCount} file{modifiedCount !== 1 ? 's' : ''} changed
                </Badge>
              </div>
            </DialogHeader>
            <textarea
              ref={inputRef}
              className="w-full resize-y rounded-lg border border-input bg-[var(--bg-input)] px-3 py-2.5 text-[13px] text-foreground placeholder:text-muted-foreground outline-none transition-colors focus:border-ring"
              placeholder="Commit message..."
              value={message}
              onChange={(e) => setMessage(e.target.value)}
              onKeyDown={handleKeyDown}
              rows={3}
            />
            <DialogFooter className="flex-row items-center justify-between sm:justify-between">
              <span className="text-[11px] text-muted-foreground">Cmd+Enter to commit</span>
              <div className="flex gap-2">
                <Button variant="outline" onClick={onClose}>
                  Cancel
                </Button>
                <Button onClick={handleSubmit} disabled={!message.trim()}>
                  Commit & Push
                </Button>
              </div>
            </DialogFooter>
          </DialogContent>
        </Dialog>
      )
    }