diff --git a/.prettierignore b/.prettierignore index fe779f6e0f2..a555741545f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -11,6 +11,7 @@ # Symlinked skill directories (cause EISDIR errors in prettier) .cursor/skills .claude/skills +.claude/worktrees # Auto-generated TanStack Router file apps/console/src/routeTree.gen.ts \ No newline at end of file diff --git a/libs/domains/organizations/feature/src/lib/organization-overview/section-changelog/section-changelog.tsx b/libs/domains/organizations/feature/src/lib/organization-overview/section-changelog/section-changelog.tsx index 24cb984c59f..5f60a16a0cf 100644 --- a/libs/domains/organizations/feature/src/lib/organization-overview/section-changelog/section-changelog.tsx +++ b/libs/domains/organizations/feature/src/lib/organization-overview/section-changelog/section-changelog.tsx @@ -1,35 +1,74 @@ -import { Heading, Icon, Section } from '@qovery/shared/ui' +import { Badge, Heading, Icon, Section } from '@qovery/shared/ui' import { dateFullFormat } from '@qovery/shared/util-dates' +import { useLocalStorage } from '@qovery/shared/util-hooks' import { useChangelogs } from '@qovery/shared/webflow/feature' +const SEEN_CHANGELOG_DATE_KEY = 'qovery-seen-changelog-date' +const ONE_WEEK_MS = 7 * 24 * 60 * 60 * 1000 + +function isRecentChangelog(firstPublishedAt: string): boolean { + return Date.now() - new Date(firstPublishedAt).getTime() < ONE_WEEK_MS +} + +function isUnseenChangelog(firstPublishedAt: string, seenDate: string | null): boolean { + return seenDate === null || firstPublishedAt > seenDate +} + +function shouldShowNewBadge(firstPublishedAt: string | undefined, seenDate: string | null): boolean { + if (firstPublishedAt === undefined) { + return false + } + + return isRecentChangelog(firstPublishedAt) && isUnseenChangelog(firstPublishedAt, seenDate) +} + export function SectionChangelog() { const { data: changelogs = [] } = useChangelogs() + const [seenChangelogDate, setSeenChangelogDate] = useLocalStorage(SEEN_CHANGELOG_DATE_KEY, null) if (changelogs.length === 0) { return null } + const showNewBadge = shouldShowNewBadge(changelogs[0].firstPublishedAt, seenChangelogDate) + return (
Changelog - {changelogs.map((changelog) => ( - -

{changelog.name}

- - {dateFullFormat(changelog.firstPublishedAt, 'UTC', 'dd MMM, Y')} - -
- ))} + {changelogs.map((changelog, index) => { + const isLatest = index === 0 + + return ( + { + if (isLatest && showNewBadge) { + setSeenChangelogDate(changelog.firstPublishedAt) + } + }} + className="flex flex-col gap-2 rounded-lg border border-neutral p-4 text-neutral transition-colors hover:bg-surface-neutral-subtle" + > +
+

{changelog.name}

+ {isLatest && showNewBadge && ( + + New + + )} +
+ + {dateFullFormat(changelog.firstPublishedAt, 'UTC', 'dd MMM, Y')} + +
+ ) + })}
) }