' . icon('question') . ''; } } // ------------------------------------------------------------------------ if (! function_exists('data_table')) { /** * Data table component * * Creates a stylized table. * * @param array> $columns array of associate arrays with `header` and `cell` keys where `cell` is a function with a row of $data as parameter * @param mixed[] $data data to loop through and display in rows * @param mixed ...$rest Any other argument to pass to the `cell` function */ function data_table(array $columns, array $data = [], string $class = '', ...$rest): string { $table = new Table(); $template = [ 'table_open' => '', 'thead_open' => '', 'heading_cell_start' => '', 'row_alt_start' => '', ]; $table->setTemplate($template); $tableHeaders = []; foreach ($columns as $column) { $tableHeaders[] = $column['header']; } $table->setHeading($tableHeaders); if (($dataCount = count($data)) !== 0) { for ($i = 0; $i < $dataCount; ++$i) { $row = $data[$i]; $rowData = []; foreach ($columns as $column) { $rowData[] = $column['cell']($row, ...$rest); } $table->addRow($rowData); } } else { $table->addRow([ [ 'colspan' => count($tableHeaders), 'class' => 'px-4 py-2 italic font-semibold text-center', 'data' => lang('Common.no_data'), ], ]); } return '
' . $table->generate() . '
'; } } // ------------------------------------------------------------------------ if (! function_exists('publication_pill')) { /** * Publication pill component * * Shows the stylized publication datetime in regards to current datetime. */ function publication_pill(?Time $publicationDate, string $publicationStatus, string $customClass = ''): string { $class = match ($publicationStatus) { 'published' => 'text-pine-500 border-pine-500 bg-pine-50', 'scheduled' => 'text-red-600 border-red-600 bg-red-50', 'not_published' => 'text-gray-600 border-gray-600 bg-gray-50', default => 'text-gray-600 border-gray-600 bg-gray-50', }; $label = lang('Episode.publication_status.' . $publicationStatus); return '' . $label . ''; } } // ------------------------------------------------------------------------ if (! function_exists('publication_button')) { /** * Publication button component * * Displays the appropriate publication button depending on the publication post. */ function publication_button(int $podcastId, int $episodeId, string $publicationStatus): string { /** @phpstan-ignore-next-line */ switch ($publicationStatus) { case 'not_published': $label = lang('Episode.publish'); $route = route_to('episode-publish', $podcastId, $episodeId); $variant = 'primary'; $iconLeft = 'upload-cloud'; break; case 'scheduled': $label = lang('Episode.publish_edit'); $route = route_to('episode-publish_edit', $podcastId, $episodeId); $variant = 'warning'; $iconLeft = 'upload-cloud'; break; case 'published': $label = lang('Episode.unpublish'); $route = route_to('episode-unpublish', $podcastId, $episodeId); $variant = 'danger'; $iconLeft = 'cloud-off'; break; default: $label = ''; $route = ''; $variant = ''; $iconLeft = ''; break; } return <<{$label} CODE_SAMPLE; } } // ------------------------------------------------------------------------ if (! function_exists('episode_numbering')) { /** * Returns relevant translated episode numbering. * * @param bool $isAbbr component will show abbreviated numbering if true */ function episode_numbering( ?int $episodeNumber = null, ?int $seasonNumber = null, string $class = '', bool $isAbbr = false ): string { if (! $episodeNumber && ! $seasonNumber) { return ''; } $transKey = ''; $args = []; if ($episodeNumber !== null) { $args['episodeNumber'] = sprintf('%02d', $episodeNumber); } if ($seasonNumber !== null) { $args['seasonNumber'] = sprintf('%02d', $seasonNumber); } if ($episodeNumber !== null && $seasonNumber !== null) { $transKey = 'Episode.season_episode'; } elseif ($episodeNumber !== null && $seasonNumber === null) { $transKey = 'Episode.number'; } elseif ($episodeNumber === null && $seasonNumber !== null) { $transKey = 'Episode.season'; } if ($isAbbr) { return '' . lang($transKey . '_abbr', $args) . ''; } return '' . lang($transKey, $args) . ''; } } // ------------------------------------------------------------------------ if (! function_exists('location_link')) { /** * Returns link to display from location info */ function location_link(?Location $location, string $class = ''): string { if ($location === null) { return ''; } return anchor( $location->url, icon('map-pin', 'mr-2') . $location->name, [ 'class' => 'inline-flex items-baseline hover:underline focus:ring-accent' . ($class === '' ? '' : " {$class}"), 'target' => '_blank', 'rel' => 'noreferrer noopener', ], ); } } // ------------------------------------------------------------------------ if (! function_exists('audio_player')) { /** * Returns audio player */ function audio_player(string $source, string $mediaType, string $class = ''): string { $language = service('request') ->getLocale(); return << CODE_SAMPLE; } } // ------------------------------------------------------------------------ if (! function_exists('relative_time')) { function relative_time(Time $time, string $class = ''): string { $formatter = new IntlDateFormatter(service( 'request' )->getLocale(), IntlDateFormatter::MEDIUM, IntlDateFormatter::NONE); $translatedDate = $time->toLocalizedString($formatter->getPattern()); $datetime = $time->format(DateTime::ISO8601); return << CODE_SAMPLE; } } // ------------------------------------------------------------------------ if (! function_exists('explicit_badge')) { function explicit_badge(bool $isExplicit, string $class = ''): string { if (! $isExplicit) { return ''; } $explicitLabel = lang('Common.explicit'); return <<{$explicitLabel} CODE_SAMPLE; } } // ------------------------------------------------------------------------ if (! function_exists('category_label')) { function category_label(Category $category): string { $categoryLabel = ''; if ($category->parent_id !== null) { $categoryLabel .= lang('Podcast.category_options.' . $category->parent->code) . ' › '; } return $categoryLabel . lang('Podcast.category_options.' . $category->code); } } // ------------------------------------------------------------------------
', 'cell_start' => '', 'cell_alt_start' => '', 'row_start' => '