Public/Show-SummitSession.ps1

function Show-SummitSession {
    <#
    .SYNOPSIS
        Displays summit session details in a formatted Spectre.Console panel.
 
    .DESCRIPTION
        Renders session information as styled panels with colored borders,
        speaker info, tags, and full description. Accepts pipeline input from
        Get-SummitSchedule or Get-SummitSession, or searches by title.
 
    .PARAMETER Title
        Search for sessions by title (wildcard match).
 
    .PARAMETER Year
        The summit year to query when searching by title. Defaults to the current year.
 
    .PARAMETER InputObject
        A session or session detail object. Accepts pipeline input.
 
    .PARAMETER BorderColor
        The Spectre border color for the panel. Defaults to Cyan1.
 
    .EXAMPLE
        Show-SummitSession -Title "State of the Shell"
 
    .EXAMPLE
        Get-SummitSchedule -Category Keynote | Show-SummitSession
 
    .EXAMPLE
        Get-SummitSession -Title "PowerShell" | Show-SummitSession -BorderColor Gold1
 
    .LINK
        https://github.com/jorgeasaurus/PwShSummitSched
    #>

    [CmdletBinding(DefaultParameterSetName = 'BySearch')]
    [Alias('showsession')]
    param(
        [Parameter(Mandatory, ParameterSetName = 'BySearch', Position = 0)]
        [string]$Title,

        [Parameter(ParameterSetName = 'BySearch')]
        [int]$Year = (Get-Date).Year,

        [Parameter(Mandatory, ParameterSetName = 'ByPipeline', ValueFromPipeline)]
        $InputObject,

        [string]$BorderColor = 'Cyan1'
    )

    begin {
        $detailCache = @{}
    }

    process {
        # Resolve to SessionDetail objects
        $sessions = @()

        if ($PSCmdlet.ParameterSetName -eq 'BySearch') {
            $sessions = @(Get-SummitSession -Title $Title -Year $Year)
        }
        elseif ($InputObject.PSObject.TypeNames -contains 'SummitSchedule.SessionDetail') {
            $sessions = @($InputObject)
        }
        elseif ($InputObject.PSObject.TypeNames -contains 'SummitSchedule.Session') {
            $searchYear = $InputObject.Year
            if (-not $detailCache.ContainsKey($searchYear)) {
                $dataFile = Join-Path $script:DataPath "$searchYear.json"
                if (Test-Path $dataFile) {
                    $detailCache[$searchYear] = Get-Content -Path $dataFile -Raw | ConvertFrom-Json
                }
            }
            if ($detailCache.ContainsKey($searchYear)) {
                $raw = $detailCache[$searchYear]
                $r = $raw | Where-Object { $_.EventId -eq $InputObject.EventId } | Select-Object -First 1
                if ($r) {
                    $sessions = @([PSCustomObject]@{
                        Title          = $r.Title
                        Day            = $r.Day
                        Date           = $r.Date
                        Time           = $r.Time
                        Speaker        = $r.Speaker
                        SpeakerCompany = $r.SpeakerCompany
                        Room           = $r.Room
                        Category       = $r.Category
                        Tags           = $r.Tags
                        Description    = $r.Description
                        EventId        = $r.EventId
                        Url            = $r.Url
                        Year           = [int]$r.Year
                    })
                }
            }
        }

        foreach ($s in $sessions) {
            $lines = [System.Collections.Generic.List[string]]::new()

            # Schedule info
            $lines.Add("[Grey]$($s.Day), $($s.Date) | $($s.Time)[/]")
            $lines.Add("[Grey]$($s.Room)[/]")
            $lines.Add('')

            # Speaker
            if ($s.Speaker) {
                $speakerLine = "[SpringGreen2]$($s.Speaker)[/]"
                if ($s.SpeakerCompany) {
                    $speakerLine += " [Grey italic]- $($s.SpeakerCompany)[/]"
                }
                $lines.Add($speakerLine)
                $lines.Add('')
            }

            # Tags
            if ($s.Tags) {
                $tagBadges = ($s.Tags -split ',\s*' | ForEach-Object { "[Gold1]$_[/]" }) -join ' '
                $lines.Add($tagBadges)
                $lines.Add('')
            }

            # Description
            if ($s.Description) {
                $escapedDesc = $s.Description -replace '\[', '[[' -replace '\]', ']]'
                $lines.Add($escapedDesc)
            }

            # URL
            if ($s.Url) {
                $lines.Add('')
                $lines.Add("[dim][link=$($s.Url)]$($s.Url)[/][/]")
            }

            $body = $lines -join "`n"
            $panelTitle = "[bold]$($s.Title)[/]"

            $body | Format-SpectrePanel -Header $panelTitle -Color $BorderColor -Expand | Out-SpectreHost
        }
    }
}