Private/UI/New-PIMDurationPanel.ps1

function New-PIMDurationPanel {
    <#
    .SYNOPSIS
        Creates a duration and justification panel for PIM activation forms.
     
    .DESCRIPTION
        Creates a Windows Forms panel containing controls for setting activation duration
        (hours/minutes) and providing justification text. Includes validation and character
        counting for the justification field.
     
    .EXAMPLE
        $durationPanel = New-PIMDurationPanel
        $form.Controls.Add($durationPanel)
         
        Creates and adds a duration panel to a form.
     
    .OUTPUTS
        System.Windows.Forms.Panel
        A panel containing duration controls (hours/minutes dropdowns) and justification textbox.
     
    .NOTES
        - Default duration is set to 8 hours, 0 minutes
        - Minutes are limited to 15-minute intervals (0, 15, 30, 45)
        - Justification is limited to 500 characters with live counter
        - Panel supports anchoring for responsive layouts
    #>

    [CmdletBinding()]
    param()
    
    # Main container panel
    $panel = New-Object System.Windows.Forms.Panel -Property @{
        Name = 'pnlDuration'
        BackColor = [System.Drawing.Color]::White
        BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
    }
    
    # Duration controls group
    $grpDuration = New-Object System.Windows.Forms.GroupBox -Property @{
        Text = 'Activation Duration'
        Location = [System.Drawing.Point]::new(10, 10)
        Size = [System.Drawing.Size]::new(300, 100)
        Font = [System.Drawing.Font]::new("Segoe UI", 10, [System.Drawing.FontStyle]::Bold)
    }
    
    # Hours selection
    $grpDuration.Controls.AddRange(@(
        (New-Object System.Windows.Forms.Label -Property @{
            Text = 'Hours:'
            Location = [System.Drawing.Point]::new(10, 30)
            Size = [System.Drawing.Size]::new(50, 20)
            Font = [System.Drawing.Font]::new("Segoe UI", 9)
        }),
        ($cmbHours = New-Object System.Windows.Forms.ComboBox -Property @{
            Name = 'cmbHours'
            Location = [System.Drawing.Point]::new(65, 28)
            Size = [System.Drawing.Size]::new(60, 23)
            DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
            Font = [System.Drawing.Font]::new("Segoe UI", 9)
        })
    ))
    
    0..23 | ForEach-Object { [void]$cmbHours.Items.Add($_) }
    $cmbHours.SelectedIndex = 8
    
    # Minutes selection
    $grpDuration.Controls.AddRange(@(
        (New-Object System.Windows.Forms.Label -Property @{
            Text = 'Minutes:'
            Location = [System.Drawing.Point]::new(140, 30)
            Size = [System.Drawing.Size]::new(60, 20)
            Font = [System.Drawing.Font]::new("Segoe UI", 9)
        }),
        ($cmbMinutes = New-Object System.Windows.Forms.ComboBox -Property @{
            Name = 'cmbMinutes'
            Location = [System.Drawing.Point]::new(205, 28)
            Size = [System.Drawing.Size]::new(60, 23)
            DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
            Font = [System.Drawing.Font]::new("Segoe UI", 9)
        })
    ))
    
    0..59 | Where-Object { $_ % 15 -eq 0 } | ForEach-Object { [void]$cmbMinutes.Items.Add($_) }
    $cmbMinutes.SelectedIndex = 0
    
    # Duration info
    $grpDuration.Controls.Add((New-Object System.Windows.Forms.Label -Property @{
        Name = 'lblDurationInfo'
        Text = 'Maximum allowed duration will be enforced per role'
        Location = [System.Drawing.Point]::new(10, 60)
        Size = [System.Drawing.Size]::new(280, 30)
        Font = [System.Drawing.Font]::new("Segoe UI", 8)
        ForeColor = [System.Drawing.Color]::FromArgb(100, 100, 100)
    }))
    
    $panel.Controls.Add($grpDuration)
    
    # Justification group
    $grpJustification = New-Object System.Windows.Forms.GroupBox -Property @{
        Text = 'Justification'
        Location = [System.Drawing.Point]::new(330, 10)
        Size = [System.Drawing.Size]::new(800, 100)
        Font = [System.Drawing.Font]::new("Segoe UI", 10, [System.Drawing.FontStyle]::Bold)
        Anchor = ([System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right)
    }
    
    # Character counter
    $lblCharCount = New-Object System.Windows.Forms.Label -Property @{
        Name = 'lblCharCount'
        Text = '0 / 500'
        Location = [System.Drawing.Point]::new(720, 5)
        Size = [System.Drawing.Size]::new(70, 20)
        TextAlign = 'MiddleRight'
        Font = [System.Drawing.Font]::new("Segoe UI", 8)
        ForeColor = [System.Drawing.Color]::FromArgb(100, 100, 100)
        Anchor = ([System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right)
    }
    
    # Justification textbox
    $txtJustification = New-Object System.Windows.Forms.TextBox -Property @{
        Name = 'txtJustification'
        Location = [System.Drawing.Point]::new(10, 25)
        Size = [System.Drawing.Size]::new(780, 65)
        Multiline = $true
        ScrollBars = [System.Windows.Forms.ScrollBars]::Vertical
        Font = [System.Drawing.Font]::new("Segoe UI", 9)
        MaxLength = 500
        Anchor = ([System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right)
    }
    
    # Character count update handler
    $txtJustification.Add_TextChanged({
        $charCount = $this.Parent.Controls.Find('lblCharCount', $true)[0]
        if ($charCount) {
            $charCount.Text = "$($this.Text.Length) / 500"
            $charCount.ForeColor = if ($this.Text.Length -ge 450) { 
                [System.Drawing.Color]::FromArgb(200, 100, 0) 
            } else { 
                [System.Drawing.Color]::FromArgb(100, 100, 100) 
            }
        }
    })
    
    $grpJustification.Controls.AddRange(@($lblCharCount, $txtJustification))
    $panel.Controls.Add($grpJustification)
    
    return $panel
}