import React, { useEffect, useMemo, useState } from 'react' import apiFetch from '@wordpress/api-fetch' import { Card, CardBody, CheckboxControl, Notice, Spinner, TextControl, } from '@wordpress/components' import { useI18n } from '@wordpress/react-i18n' import { sprintf } from '@wordpress/i18n' import { useEnableWpCompatOverlaySlot } from '@wordpress/ui' import { CHANGELOG_TYPES, ChangelogEntry, ChangelogResponse, formatChangelogDate, } from './model/changelog' import './styles.scss' const Changelog = () => { const { __ } = useI18n() useEnableWpCompatOverlaySlot() const [entries, setEntries] = useState>([]) const [currentVersion, setCurrentVersion] = useState('') const [isLoading, setIsLoading] = useState(true) const [hasError, setHasError] = useState(false) const [search, setSearch] = useState('') const [types, setTypes] = useState>([]) const typeLabels: Record = { new: __('New', 'posten-bring-checkout'), improvement: __('Improvement', 'posten-bring-checkout'), fix: __('Fix', 'posten-bring-checkout'), deprecated: __('Deprecated', 'posten-bring-checkout'), removed: __('Removed', 'posten-bring-checkout'), } useEffect(() => { const fetchChangelog = async () => { try { const response: ChangelogResponse = await apiFetch({ path: '/posten-bring-checkout/changelog', }) setEntries(response?.entries || []) setCurrentVersion(response?.currentVersion || '') // The endpoint answers 200 even when the feed is unreachable, so that // the installed version can still be shown. The flag is what tells the // two apart. setHasError(false === response?.feedOk) } catch (error) { setHasError(true) } finally { setIsLoading(false) } } fetchChangelog() }, []) const visible = useMemo(() => { const query = search.trim().toLowerCase() return entries.filter(entry => { if (types.length && !types.includes(entry.type)) { return false } if (!query) { return true } return `${entry.title} ${entry.contentHtml}`.toLowerCase().includes(query) }) }, [entries, search, types]) const notInstalled = useMemo( () => entries.filter(entry => !entry.installed), [entries] ) const toggleType = (type: string) => setTypes(current => current.includes(type) ? current.filter(it => it !== type) : [...current, type] ) const filtered = types.length > 0 || search.trim() !== '' return (

{__("What's new in Posten Bring Checkout", 'posten-bring-checkout')}

{__( 'Every change we ship to the WooCommerce plugin, newest first. Filter by type or search to find a specific change.', 'posten-bring-checkout' )}

{notInstalled.length > 0 && (
{__( 'Some changes below need a newer version of the plugin.', 'posten-bring-checkout' )}
)} {/* Nothing pending is worth saying out loud, not just the absence of a warning. The trophy sits outside the translated string so it cannot be lost in translation. */} {!isLoading && !hasError && currentVersion && entries.length > 0 && notInstalled.length === 0 && (
{'🏆 '} {__('You are up to date.', 'posten-bring-checkout')}
)} {isLoading && ( )} {!isLoading && hasError && ( {__( 'We could not reach the changelog feed. Try again in a few minutes.', 'posten-bring-checkout' )} )} {!isLoading && !hasError && visible.length === 0 && ( {entries.length === 0 ? __('There are no updates to show yet.', 'posten-bring-checkout') : __('No updates match your filters.', 'posten-bring-checkout')} )} {visible.map(entry => (
{formatChangelogDate(entry.date)}

{entry.title}

{entry.type && ( {typeLabels[entry.type] || entry.type} )} {entry.version && ( {`v${entry.version}`} )} {!entry.installed && ( {__('Requires update', 'posten-bring-checkout')} )}
))}
{currentVersion && ( {__('Installed version', 'posten-bring-checkout')} {`v${currentVersion}`} )}
{__('Type of change', 'posten-bring-checkout')} {CHANGELOG_TYPES.map(type => ( toggleType(type)} /> ))}

{filtered ? sprintf( /* translators: 1: number of matching updates, 2: total number of updates. */ __('%1$d of %2$d updates', 'posten-bring-checkout'), visible.length, entries.length ) : sprintf( /* translators: %d is the number of updates. */ __('%d updates', 'posten-bring-checkout'), entries.length )}

) } export default Changelog