remove changelog page and sidebar link
Drop /dashboard/changelog route, ChangelogTab component, useChangelog hook, the sidebar nav item, and the related tr/en translation keys. API-side changelog schemas are untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,118 +0,0 @@
|
||||
import { useChangelog } from "@/hooks/use-changelog";
|
||||
import { useTranslation } from "@/lib/i18n";
|
||||
import type { ChangelogEntry } from "@sase/shared";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
Badge,
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
Skeleton,
|
||||
} from "@sase/ui";
|
||||
import { CalendarDays } from "lucide-react";
|
||||
|
||||
function formatDate(iso: string, locale: "tr" | "en"): string {
|
||||
const date = new Date(iso);
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
};
|
||||
return date.toLocaleDateString(locale === "tr" ? "tr-TR" : "en-US", options);
|
||||
}
|
||||
|
||||
function changeTypeLabel(
|
||||
changeType: ChangelogEntry["changeType"],
|
||||
t: (key: string) => string,
|
||||
): string {
|
||||
return t(`settings.changelog.changeType.${changeType}`);
|
||||
}
|
||||
|
||||
function ChangelogSkeleton() {
|
||||
return (
|
||||
<div className="space-y-0">
|
||||
{[1, 2, 3].map((i) => (
|
||||
<div key={i} className="relative pb-6 pl-8">
|
||||
<div className="absolute left-0 top-1.5 h-2.5 w-2.5 rounded-full bg-muted-foreground/20" />
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="h-5 w-16 rounded-md" />
|
||||
<Skeleton className="h-5 w-48" />
|
||||
</div>
|
||||
<Skeleton className="h-4 w-28" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ChangelogEmpty({ t }: { t: (key: string) => string }) {
|
||||
return (
|
||||
<Card className="border-dashed">
|
||||
<CardHeader className="text-center">
|
||||
<CalendarDays className="mx-auto h-10 w-10 text-muted-foreground" />
|
||||
<CardTitle>{t("settings.changelog.emptyTitle")}</CardTitle>
|
||||
<CardDescription>{t("settings.changelog.emptyDescription")}</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export function ChangelogTab() {
|
||||
const { data: entries, isLoading } = useChangelog();
|
||||
const { t, locale } = useTranslation();
|
||||
|
||||
if (isLoading) {
|
||||
return <ChangelogSkeleton />;
|
||||
}
|
||||
|
||||
if (!entries || entries.length === 0) {
|
||||
return <ChangelogEmpty t={t} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>{t("settings.changelog.title")}</CardTitle>
|
||||
<CardDescription>{t("settings.changelog.description")}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Accordion
|
||||
type="single"
|
||||
collapsible
|
||||
className="relative border-l-2 border-muted-foreground/20"
|
||||
>
|
||||
{entries.map((entry) => (
|
||||
<AccordionItem key={entry.id} value={entry.id} className="border-b-0 pl-6">
|
||||
<div className="absolute left-[-5px] mt-6 h-2.5 w-2.5 rounded-full border-2 border-background bg-foreground dark:bg-primary" />
|
||||
<AccordionTrigger className="py-3 hover:no-underline">
|
||||
<div className="flex flex-col items-start gap-1.5 text-left">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Badge changeType={entry.changeType}>
|
||||
{changeTypeLabel(entry.changeType, t)}
|
||||
</Badge>
|
||||
<span className="font-medium">{entry.title}</span>
|
||||
</div>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{formatDate(entry.publishedAt, locale)}
|
||||
</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="text-sm text-muted-foreground leading-relaxed whitespace-pre-wrap">
|
||||
{entry.description}
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
))}
|
||||
</Accordion>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { api } from "@/lib/api-client";
|
||||
import type { ChangelogEntry } from "@sase/shared";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
export function useChangelog() {
|
||||
return useQuery({
|
||||
queryKey: ["changelog"],
|
||||
queryFn: () => api.get<ChangelogEntry[]>("/changelog"),
|
||||
staleTime: 30 * 60 * 1000, // 30 min — matches Redis cache TTL
|
||||
});
|
||||
}
|
||||
@@ -74,6 +74,7 @@
|
||||
"dashboard": "Dashboard",
|
||||
"search": "Search",
|
||||
"history": "History",
|
||||
"experts": "Parts Experts",
|
||||
"catalog": "Catalog",
|
||||
"subscription": "Subscription",
|
||||
"billing": "Payment",
|
||||
@@ -82,7 +83,6 @@
|
||||
"logout": "Log Out",
|
||||
"contact": "Contact",
|
||||
"blog": "Blog",
|
||||
"changelog": "What's New",
|
||||
"account": "Account",
|
||||
"sectionMain": "Main Menu",
|
||||
"sectionAccount": "Account",
|
||||
@@ -522,7 +522,6 @@
|
||||
"connections": "Connections",
|
||||
"referral": "Referral",
|
||||
"account": "Account",
|
||||
"changelog": "Changelog",
|
||||
"notifications": "Notifications"
|
||||
},
|
||||
"preferences": {
|
||||
@@ -593,17 +592,6 @@
|
||||
"typeConfirm": "Type 'DELETE' to confirm",
|
||||
"confirmWord": "DELETE"
|
||||
},
|
||||
"changelog": {
|
||||
"title": "Changelog",
|
||||
"description": "Latest platform updates, new features, and bug fixes.",
|
||||
"emptyTitle": "No updates yet",
|
||||
"emptyDescription": "Platform updates will appear here soon.",
|
||||
"changeType": {
|
||||
"fix": "Fix",
|
||||
"feature": "New Feature",
|
||||
"improvement": "Improvement"
|
||||
}
|
||||
},
|
||||
"notifications": {
|
||||
"title": "Notification preferences",
|
||||
"description": "Choose which lifecycle e-mails you want to receive. Account security and payment notifications keep coming."
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
"dashboard": "Gösterge Paneli",
|
||||
"search": "Arama",
|
||||
"history": "Geçmiş",
|
||||
"experts": "Parça Uzmanları",
|
||||
"catalog": "Katalog",
|
||||
"subscription": "Abonelik",
|
||||
"billing": "Ödeme",
|
||||
@@ -82,7 +83,6 @@
|
||||
"logout": "Çıkış Yap",
|
||||
"contact": "İletişim",
|
||||
"blog": "Blog",
|
||||
"changelog": "Yenilikler",
|
||||
"account": "Hesap",
|
||||
"sectionMain": "Ana Menü",
|
||||
"sectionAccount": "Hesap",
|
||||
@@ -522,7 +522,6 @@
|
||||
"connections": "Bağlantılar",
|
||||
"referral": "Referans",
|
||||
"account": "Hesap",
|
||||
"changelog": "Değişiklik Günlüğü",
|
||||
"notifications": "Bildirimler"
|
||||
},
|
||||
"preferences": {
|
||||
@@ -593,17 +592,6 @@
|
||||
"typeConfirm": "Onaylamak için 'SİL' yazın",
|
||||
"confirmWord": "SİL"
|
||||
},
|
||||
"changelog": {
|
||||
"title": "Değişiklik Günlüğü",
|
||||
"description": "Platformdaki son güncellemeler, yeni özellikler ve hata düzeltmeleri.",
|
||||
"emptyTitle": "Henüz güncelleme yok",
|
||||
"emptyDescription": "Yakında platform güncellemeleri burada görünecek.",
|
||||
"changeType": {
|
||||
"fix": "Düzeltme",
|
||||
"feature": "Yeni Özellik",
|
||||
"improvement": "Geliştirme"
|
||||
}
|
||||
},
|
||||
"notifications": {
|
||||
"title": "Bildirim tercihleri",
|
||||
"description": "Hangi lifecycle maillerini almak istediğini seç. Hesap güvenliği ve ödeme bildirimleri her zaman gelmeye devam eder."
|
||||
|
||||
@@ -21,12 +21,12 @@ import { Route as AboutRouteImport } from './routes/about'
|
||||
import { Route as AuthRouteImport } from './routes/_auth'
|
||||
import { Route as IndexRouteImport } from './routes/index'
|
||||
import { Route as DashboardIndexRouteImport } from './routes/dashboard/index'
|
||||
import { Route as DashboardUzmanlarRouteImport } from './routes/dashboard/uzmanlar'
|
||||
import { Route as DashboardSettingsRouteImport } from './routes/dashboard/settings'
|
||||
import { Route as DashboardServiceTestRouteImport } from './routes/dashboard/service-test'
|
||||
import { Route as DashboardSearchRouteImport } from './routes/dashboard/search'
|
||||
import { Route as DashboardHistoryRouteImport } from './routes/dashboard/history'
|
||||
import { Route as DashboardContactRouteImport } from './routes/dashboard/contact'
|
||||
import { Route as DashboardChangelogRouteImport } from './routes/dashboard/changelog'
|
||||
import { Route as DashboardBlogRouteImport } from './routes/dashboard/blog'
|
||||
import { Route as DashboardBillingRouteImport } from './routes/dashboard/billing'
|
||||
import { Route as BlogSlugRouteImport } from './routes/blog_/$slug'
|
||||
@@ -117,6 +117,11 @@ const DashboardIndexRoute = DashboardIndexRouteImport.update({
|
||||
path: '/',
|
||||
getParentRoute: () => DashboardRoute,
|
||||
} as any)
|
||||
const DashboardUzmanlarRoute = DashboardUzmanlarRouteImport.update({
|
||||
id: '/uzmanlar',
|
||||
path: '/uzmanlar',
|
||||
getParentRoute: () => DashboardRoute,
|
||||
} as any)
|
||||
const DashboardSettingsRoute = DashboardSettingsRouteImport.update({
|
||||
id: '/settings',
|
||||
path: '/settings',
|
||||
@@ -142,11 +147,6 @@ const DashboardContactRoute = DashboardContactRouteImport.update({
|
||||
path: '/contact',
|
||||
getParentRoute: () => DashboardRoute,
|
||||
} as any)
|
||||
const DashboardChangelogRoute = DashboardChangelogRouteImport.update({
|
||||
id: '/changelog',
|
||||
path: '/changelog',
|
||||
getParentRoute: () => DashboardRoute,
|
||||
} as any)
|
||||
const DashboardBlogRoute = DashboardBlogRouteImport.update({
|
||||
id: '/blog',
|
||||
path: '/blog',
|
||||
@@ -331,12 +331,12 @@ export interface FileRoutesByFullPath {
|
||||
'/blog/$slug': typeof BlogSlugRoute
|
||||
'/dashboard/billing': typeof DashboardBillingRoute
|
||||
'/dashboard/blog': typeof DashboardBlogRoute
|
||||
'/dashboard/changelog': typeof DashboardChangelogRoute
|
||||
'/dashboard/contact': typeof DashboardContactRoute
|
||||
'/dashboard/history': typeof DashboardHistoryRoute
|
||||
'/dashboard/search': typeof DashboardSearchRoute
|
||||
'/dashboard/service-test': typeof DashboardServiceTestRoute
|
||||
'/dashboard/settings': typeof DashboardSettingsRoute
|
||||
'/dashboard/uzmanlar': typeof DashboardUzmanlarRoute
|
||||
'/dashboard/': typeof DashboardIndexRoute
|
||||
'/dashboard/admin/analytics': typeof DashboardAdminAnalyticsRoute
|
||||
'/dashboard/admin/copy-logs': typeof DashboardAdminCopyLogsRoute
|
||||
@@ -379,12 +379,12 @@ export interface FileRoutesByTo {
|
||||
'/blog/$slug': typeof BlogSlugRoute
|
||||
'/dashboard/billing': typeof DashboardBillingRoute
|
||||
'/dashboard/blog': typeof DashboardBlogRoute
|
||||
'/dashboard/changelog': typeof DashboardChangelogRoute
|
||||
'/dashboard/contact': typeof DashboardContactRoute
|
||||
'/dashboard/history': typeof DashboardHistoryRoute
|
||||
'/dashboard/search': typeof DashboardSearchRoute
|
||||
'/dashboard/service-test': typeof DashboardServiceTestRoute
|
||||
'/dashboard/settings': typeof DashboardSettingsRoute
|
||||
'/dashboard/uzmanlar': typeof DashboardUzmanlarRoute
|
||||
'/dashboard': typeof DashboardIndexRoute
|
||||
'/dashboard/admin/analytics': typeof DashboardAdminAnalyticsRoute
|
||||
'/dashboard/admin/copy-logs': typeof DashboardAdminCopyLogsRoute
|
||||
@@ -430,12 +430,12 @@ export interface FileRoutesById {
|
||||
'/blog_/$slug': typeof BlogSlugRoute
|
||||
'/dashboard/billing': typeof DashboardBillingRoute
|
||||
'/dashboard/blog': typeof DashboardBlogRoute
|
||||
'/dashboard/changelog': typeof DashboardChangelogRoute
|
||||
'/dashboard/contact': typeof DashboardContactRoute
|
||||
'/dashboard/history': typeof DashboardHistoryRoute
|
||||
'/dashboard/search': typeof DashboardSearchRoute
|
||||
'/dashboard/service-test': typeof DashboardServiceTestRoute
|
||||
'/dashboard/settings': typeof DashboardSettingsRoute
|
||||
'/dashboard/uzmanlar': typeof DashboardUzmanlarRoute
|
||||
'/dashboard/': typeof DashboardIndexRoute
|
||||
'/dashboard/admin/analytics': typeof DashboardAdminAnalyticsRoute
|
||||
'/dashboard/admin/copy-logs': typeof DashboardAdminCopyLogsRoute
|
||||
@@ -481,12 +481,12 @@ export interface FileRouteTypes {
|
||||
| '/blog/$slug'
|
||||
| '/dashboard/billing'
|
||||
| '/dashboard/blog'
|
||||
| '/dashboard/changelog'
|
||||
| '/dashboard/contact'
|
||||
| '/dashboard/history'
|
||||
| '/dashboard/search'
|
||||
| '/dashboard/service-test'
|
||||
| '/dashboard/settings'
|
||||
| '/dashboard/uzmanlar'
|
||||
| '/dashboard/'
|
||||
| '/dashboard/admin/analytics'
|
||||
| '/dashboard/admin/copy-logs'
|
||||
@@ -529,12 +529,12 @@ export interface FileRouteTypes {
|
||||
| '/blog/$slug'
|
||||
| '/dashboard/billing'
|
||||
| '/dashboard/blog'
|
||||
| '/dashboard/changelog'
|
||||
| '/dashboard/contact'
|
||||
| '/dashboard/history'
|
||||
| '/dashboard/search'
|
||||
| '/dashboard/service-test'
|
||||
| '/dashboard/settings'
|
||||
| '/dashboard/uzmanlar'
|
||||
| '/dashboard'
|
||||
| '/dashboard/admin/analytics'
|
||||
| '/dashboard/admin/copy-logs'
|
||||
@@ -579,12 +579,12 @@ export interface FileRouteTypes {
|
||||
| '/blog_/$slug'
|
||||
| '/dashboard/billing'
|
||||
| '/dashboard/blog'
|
||||
| '/dashboard/changelog'
|
||||
| '/dashboard/contact'
|
||||
| '/dashboard/history'
|
||||
| '/dashboard/search'
|
||||
| '/dashboard/service-test'
|
||||
| '/dashboard/settings'
|
||||
| '/dashboard/uzmanlar'
|
||||
| '/dashboard/'
|
||||
| '/dashboard/admin/analytics'
|
||||
| '/dashboard/admin/copy-logs'
|
||||
@@ -712,6 +712,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof DashboardIndexRouteImport
|
||||
parentRoute: typeof DashboardRoute
|
||||
}
|
||||
'/dashboard/uzmanlar': {
|
||||
id: '/dashboard/uzmanlar'
|
||||
path: '/uzmanlar'
|
||||
fullPath: '/dashboard/uzmanlar'
|
||||
preLoaderRoute: typeof DashboardUzmanlarRouteImport
|
||||
parentRoute: typeof DashboardRoute
|
||||
}
|
||||
'/dashboard/settings': {
|
||||
id: '/dashboard/settings'
|
||||
path: '/settings'
|
||||
@@ -747,13 +754,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof DashboardContactRouteImport
|
||||
parentRoute: typeof DashboardRoute
|
||||
}
|
||||
'/dashboard/changelog': {
|
||||
id: '/dashboard/changelog'
|
||||
path: '/changelog'
|
||||
fullPath: '/dashboard/changelog'
|
||||
preLoaderRoute: typeof DashboardChangelogRouteImport
|
||||
parentRoute: typeof DashboardRoute
|
||||
}
|
||||
'/dashboard/blog': {
|
||||
id: '/dashboard/blog'
|
||||
path: '/blog'
|
||||
@@ -988,12 +988,12 @@ const AuthRouteWithChildren = AuthRoute._addFileChildren(AuthRouteChildren)
|
||||
interface DashboardRouteChildren {
|
||||
DashboardBillingRoute: typeof DashboardBillingRoute
|
||||
DashboardBlogRoute: typeof DashboardBlogRoute
|
||||
DashboardChangelogRoute: typeof DashboardChangelogRoute
|
||||
DashboardContactRoute: typeof DashboardContactRoute
|
||||
DashboardHistoryRoute: typeof DashboardHistoryRoute
|
||||
DashboardSearchRoute: typeof DashboardSearchRoute
|
||||
DashboardServiceTestRoute: typeof DashboardServiceTestRoute
|
||||
DashboardSettingsRoute: typeof DashboardSettingsRoute
|
||||
DashboardUzmanlarRoute: typeof DashboardUzmanlarRoute
|
||||
DashboardIndexRoute: typeof DashboardIndexRoute
|
||||
DashboardAdminAnalyticsRoute: typeof DashboardAdminAnalyticsRoute
|
||||
DashboardAdminCopyLogsRoute: typeof DashboardAdminCopyLogsRoute
|
||||
@@ -1021,12 +1021,12 @@ interface DashboardRouteChildren {
|
||||
const DashboardRouteChildren: DashboardRouteChildren = {
|
||||
DashboardBillingRoute: DashboardBillingRoute,
|
||||
DashboardBlogRoute: DashboardBlogRoute,
|
||||
DashboardChangelogRoute: DashboardChangelogRoute,
|
||||
DashboardContactRoute: DashboardContactRoute,
|
||||
DashboardHistoryRoute: DashboardHistoryRoute,
|
||||
DashboardSearchRoute: DashboardSearchRoute,
|
||||
DashboardServiceTestRoute: DashboardServiceTestRoute,
|
||||
DashboardSettingsRoute: DashboardSettingsRoute,
|
||||
DashboardUzmanlarRoute: DashboardUzmanlarRoute,
|
||||
DashboardIndexRoute: DashboardIndexRoute,
|
||||
DashboardAdminAnalyticsRoute: DashboardAdminAnalyticsRoute,
|
||||
DashboardAdminCopyLogsRoute: DashboardAdminCopyLogsRoute,
|
||||
|
||||
@@ -31,7 +31,6 @@ import { Link, Outlet, createFileRoute, useNavigate, useRouterState } from "@tan
|
||||
import {
|
||||
BarChart3,
|
||||
BookOpen,
|
||||
CalendarDays,
|
||||
ChevronsUpDown,
|
||||
Copy,
|
||||
CreditCard,
|
||||
@@ -51,6 +50,7 @@ import {
|
||||
Shield,
|
||||
Sparkles,
|
||||
Sun,
|
||||
Trophy,
|
||||
Users,
|
||||
} from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
@@ -72,6 +72,7 @@ const mainMenuItems: readonly NavItem[] = [
|
||||
{ to: "/dashboard/search", labelKey: "nav.search", icon: Search },
|
||||
{ to: "/dashboard/catalog", labelKey: "nav.catalog", icon: Library },
|
||||
{ to: "/dashboard/history", labelKey: "nav.history", icon: History },
|
||||
{ to: "/dashboard/uzmanlar", labelKey: "nav.experts", icon: Trophy },
|
||||
];
|
||||
|
||||
const accountItems: readonly NavItem[] = [
|
||||
@@ -81,7 +82,6 @@ const accountItems: readonly NavItem[] = [
|
||||
];
|
||||
|
||||
const supportItems: readonly NavItem[] = [
|
||||
{ to: "/dashboard/changelog", labelKey: "nav.changelog", icon: CalendarDays },
|
||||
{ to: "/dashboard/contact", labelKey: "nav.contact", icon: Mail },
|
||||
{ to: "/dashboard/blog", labelKey: "nav.blog", icon: BookOpen },
|
||||
];
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { ChangelogTab } from "@/components/settings/changelog-tab";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/dashboard/changelog")({
|
||||
component: ChangelogPage,
|
||||
});
|
||||
|
||||
function ChangelogPage() {
|
||||
return (
|
||||
<div className="mx-auto max-w-3xl">
|
||||
<ChangelogTab />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user