From 1f82538e41627dfe4553479fbd205fa8846d9e40 Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 26 May 2026 19:24:02 +0000 Subject: [PATCH 1/3] feat(contact): implement Contact component with social handles - Add Contact component with GitHub, Twitter/X, LinkedIn, BlueSky, Matrix, Email - Use Card wrapper from @nipsys/lsd matching AboutMe pattern - Add Phosphor Logo icons for each platform - Include copy-to-clipboard buttons for Matrix handle and Email - Add i18n translations for EN and FR Email placeholder set to xav@example.com - needs update before merge --- src/components/contact/Contact.tsx | 143 ++++++++++++++++++++++++++++- src/i18n/messages/en.json | 15 +++ src/i18n/messages/fr.json | 15 +++ 3 files changed, 172 insertions(+), 1 deletion(-) diff --git a/src/components/contact/Contact.tsx b/src/components/contact/Contact.tsx index 65376dc..43995e8 100644 --- a/src/components/contact/Contact.tsx +++ b/src/components/contact/Contact.tsx @@ -1,3 +1,144 @@ +'use client'; + +import { Badge, Button, Typography } from '@nipsys/lsd'; +import { + TwitterLogoIcon, + LinkedinLogoIcon, + GithubLogoIcon, + EnvelopeIcon, + ChatTeardropTextIcon, + ButterflyIcon, +} from '@phosphor-icons/react'; +import { useTranslations } from 'next-intl'; +import { useState } from 'react'; +import { toast } from 'sonner'; + +interface ContactLink { + icon: React.ComponentType<{ weight?: string; size?: number }>; + labelKey: string; + href: string; + displayText: string; + copyable?: boolean; +} + export default function Contact() { - return
contact / todo
; + const t = useTranslations('Contact'); + const [copiedKey, setCopiedKey] = useState(null); + + const contactLinks: ContactLink[] = [ + { + icon: GithubLogoIcon, + labelKey: 'github', + href: 'https://github.com/nipsysdev', + displayText: 'github.com/nipsysdev', + }, + { + icon: TwitterLogoIcon, + labelKey: 'twitter', + href: 'https://x.com/nipsysdev', + displayText: '@nipsysdev', + }, + { + icon: LinkedinLogoIcon, + labelKey: 'linkedin', + href: 'https://linkedin.com/in/xavsaliniere', + displayText: 'linkedin.com/in/xavsaliniere', + }, + { + icon: ButterflyIcon, + labelKey: 'bluesky', + href: 'https://bsky.app/profile/nipsysdev.bsky.social', + displayText: '@nipsysdev.bsky.social', + }, + { + icon: ChatTeardropTextIcon, + labelKey: 'matrix', + href: 'https://matrix.to/#/@xav:nips.im', + displayText: '@xav:nips.im', + copyable: true, + }, + { + icon: EnvelopeIcon, + labelKey: 'email', + href: 'mailto:xav@example.com', + displayText: 'xav@example.com', + copyable: true, + }, + ]; + + const handleCopy = async (text: string, key: string) => { + await navigator.clipboard.writeText(text); + setCopiedKey(key); + toast.success(t('copyToast')); + setTimeout(() => setCopiedKey(null), 2000); + }; + + return ( +
+
+ {t('title')} + + {t('subtitle')} + +
+ +
+ {contactLinks.map( + ({ icon: Icon, labelKey, href, displayText, copyable }) => ( +
+
+ } + > + {t(`links.${labelKey}`)} + + + +
+ + {copyable && ( + + )} +
+ ) + )} +
+ +
+ + {t('note')} + +
+
+ ); } diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index c56638f..26f7030 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -56,6 +56,21 @@ "gpgLabel": "GPG Fingerprint", "copyToast": "GPG fingerprint copied to clipboard" }, + "Contact": { + "title": "Get in Touch", + "subtitle": "Find me on the web", + "links": { + "github": "GitHub", + "twitter": "Twitter/X", + "linkedin": "LinkedIn", + "bluesky": "BlueSky", + "matrix": "Matrix", + "email": "Email" + }, + "copyToast": "Copied to clipboard", + "copyLabel": "Copy to clipboard", + "note": "Feel free to reach out for collaboration, questions, or just to say hi!" + }, "Terminal": { "unknownCmdErr": "command not recognized", "noMatch": "no match", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index f0528bd..976772c 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -56,6 +56,21 @@ "gpgLabel": "Empreinte GPG", "copyToast": "Empreinte GPG copiée dans le presse-papier" }, + "Contact": { + "title": "Me contacter", + "subtitle": "Retrouvez-moi sur le web", + "links": { + "github": "GitHub", + "twitter": "Twitter/X", + "linkedin": "LinkedIn", + "bluesky": "BlueSky", + "matrix": "Matrix", + "email": "Courriel" + }, + "copyToast": "Copié dans le presse-papier", + "copyLabel": "Copier dans le presse-papier", + "note": "N'hésitez pas à me contacter pour collaborer, poser des questions, ou juste pour dire salut !" + }, "Terminal": { "unknownCmdErr": "commande non reconnue", "noMatch": "aucune correspondance", From ac2a95817de2dcf1df1509aa348282d996bfae86 Mon Sep 17 00:00:00 2001 From: Xavier Saliniere Date: Thu, 28 May 2026 02:30:32 -0400 Subject: [PATCH 2/3] feat(contact): restructure with grid layout, grouped sections, and extract useCopyToClipboard hook --- src/components/about-me/AboutMe.tsx | 20 ++- src/components/contact/Contact.tsx | 193 ++++++++++++++++------------ src/hooks/useCopyToClipboard.ts | 25 ++++ src/i18n/messages/en.json | 12 +- src/i18n/messages/fr.json | 12 +- 5 files changed, 159 insertions(+), 103 deletions(-) create mode 100644 src/hooks/useCopyToClipboard.ts diff --git a/src/components/about-me/AboutMe.tsx b/src/components/about-me/AboutMe.tsx index ec8f421..260db2a 100644 --- a/src/components/about-me/AboutMe.tsx +++ b/src/components/about-me/AboutMe.tsx @@ -16,16 +16,15 @@ import { TargetIcon, } from '@phosphor-icons/react'; import { useTranslations } from 'next-intl'; -import { useState } from 'react'; -import { toast } from 'sonner'; import gpgFingerprint from '@/assets/gpg-fingerprint.json'; import profileImage from '@/assets/Pro-Hacked.png'; +import { useCopyToClipboard } from '@/hooks/useCopyToClipboard'; const GPG_FINGERPRINT = gpgFingerprint.fingerprint; export default function AboutMe() { const t = useTranslations('AboutMe'); - const [copied, setCopied] = useState(false); + const { copyWithToast, isCopied } = useCopyToClipboard(); const quickInfo = [ { icon: MapPinIcon, textKey: 'badges.location' }, @@ -34,13 +33,6 @@ export default function AboutMe() { { icon: TargetIcon, textKey: 'badges.goal' }, ]; - const handleCopy = async () => { - await navigator.clipboard.writeText(GPG_FINGERPRINT); - setCopied(true); - toast.success(t('copyToast')); - setTimeout(() => setCopied(false), 200); - }; - return (
@@ -105,8 +97,12 @@ export default function AboutMe() { {t('gpgLabel')} -
diff --git a/src/components/contact/Contact.tsx b/src/components/contact/Contact.tsx index 43995e8..4e0532b 100644 --- a/src/components/contact/Contact.tsx +++ b/src/components/contact/Contact.tsx @@ -2,19 +2,26 @@ import { Badge, Button, Typography } from '@nipsys/lsd'; import { - TwitterLogoIcon, - LinkedinLogoIcon, - GithubLogoIcon, - EnvelopeIcon, - ChatTeardropTextIcon, ButterflyIcon, + ChatTeardropTextIcon, + CopyIcon, + EnvelopeIcon, + GithubLogoIcon, + type IconWeight, + LinkedinLogoIcon, + PaperPlaneTiltIcon, + TwitterLogoIcon, } from '@phosphor-icons/react'; import { useTranslations } from 'next-intl'; -import { useState } from 'react'; -import { toast } from 'sonner'; +import { useEffect, useState } from 'react'; +import { useCopyToClipboard } from '@/hooks/useCopyToClipboard'; + +// Base64 encoded email to prevent scraping (decoded after hydration) +// Generate with: btoa("your@email.com") +const ENCODED_EMAIL = 'Ym9uam91ckB4YXZpZXJzLnNo'; interface ContactLink { - icon: React.ComponentType<{ weight?: string; size?: number }>; + icon: React.ComponentType<{ weight?: IconWeight; size?: number }>; labelKey: string; href: string; displayText: string; @@ -23,14 +30,19 @@ interface ContactLink { export default function Contact() { const t = useTranslations('Contact'); - const [copiedKey, setCopiedKey] = useState(null); + const [email, setEmail] = useState(null); + const { copyWithToast, isCopied } = useCopyToClipboard(); + + useEffect(() => { + setEmail(atob(ENCODED_EMAIL)); + }, []); - const contactLinks: ContactLink[] = [ + const socialLinks: ContactLink[] = [ { icon: GithubLogoIcon, labelKey: 'github', href: 'https://github.com/nipsysdev', - displayText: 'github.com/nipsysdev', + displayText: 'nipsysdev', }, { icon: TwitterLogoIcon, @@ -39,105 +51,124 @@ export default function Contact() { displayText: '@nipsysdev', }, { - icon: LinkedinLogoIcon, - labelKey: 'linkedin', - href: 'https://linkedin.com/in/xavsaliniere', - displayText: 'linkedin.com/in/xavsaliniere', + icon: PaperPlaneTiltIcon, + labelKey: 'telegram', + href: 'https://t.me/nipsysdev', + displayText: '@nipsysdev', }, { icon: ButterflyIcon, labelKey: 'bluesky', - href: 'https://bsky.app/profile/nipsysdev.bsky.social', - displayText: '@nipsysdev.bsky.social', + href: 'https://bsky.app/profile/nipsys.bsky.social', + displayText: '@nipsys.bsky.social', + }, + { + icon: LinkedinLogoIcon, + labelKey: 'linkedin', + href: 'https://linkedin.com/in/xaviersaliniere', + displayText: 'xaviersaliniere', }, + ]; + + const directLinks: ContactLink[] = [ { icon: ChatTeardropTextIcon, labelKey: 'matrix', - href: 'https://matrix.to/#/@xav:nips.im', - displayText: '@xav:nips.im', + href: 'https://matrix.to/#/@nipsys:nips.im', + displayText: '@nipsys:nips.im', copyable: true, }, { icon: EnvelopeIcon, labelKey: 'email', - href: 'mailto:xav@example.com', - displayText: 'xav@example.com', + href: email ? `mailto:${email}` : '#', + displayText: email ?? '...', copyable: true, }, ]; - const handleCopy = async (text: string, key: string) => { - await navigator.clipboard.writeText(text); - setCopiedKey(key); - toast.success(t('copyToast')); - setTimeout(() => setCopiedKey(null), 2000); + const renderLink = ({ + icon: Icon, + labelKey, + href, + displayText, + copyable, + }: ContactLink) => { + return ( +
+ } + > + {t(`links.${labelKey}`)} + + + + + {copyable ? ( + + ) : ( +
+ )} +
+ ); }; return (
- {t('title')} + {t('title')} {t('subtitle')}
-
- {contactLinks.map( - ({ icon: Icon, labelKey, href, displayText, copyable }) => ( -
-
- } - > - {t(`links.${labelKey}`)} - - - -
- - {copyable && ( - - )} -
- ) - )} -
+
+ {/* Social Section */} + + {t('socialSection')} + + {socialLinks.map((link) => renderLink(link))} -
- - {t('note')} + {/* Direct Contact Section */} + + {t('directSection')} + {directLinks.map((link) => renderLink(link))}
); diff --git a/src/hooks/useCopyToClipboard.ts b/src/hooks/useCopyToClipboard.ts new file mode 100644 index 0000000..74863fc --- /dev/null +++ b/src/hooks/useCopyToClipboard.ts @@ -0,0 +1,25 @@ +import { useState } from 'react'; +import { toast } from 'sonner'; + +export function useCopyToClipboard() { + const [copiedKey, setCopiedKey] = useState(null); + + const copy = async (text: string, key: string = 'default') => { + await navigator.clipboard.writeText(text); + setCopiedKey(key); + setTimeout(() => setCopiedKey(null), 200); + }; + + const copyWithToast = async ( + text: string, + toastMessage: string, + key: string = 'default', + ) => { + await copy(text, key); + toast.success(toastMessage); + }; + + const isCopied = (key: string = 'default') => copiedKey === key; + + return { copy, copyWithToast, isCopied }; +} diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 26f7030..954c30f 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -35,7 +35,7 @@ "andItsUI": "and its UI!" }, "AboutMe": { - "name": "Xav [nipsysdev]", + "name": "Xav [nipsys]", "tagline": "cypherpunk / builder / digital sovereignty advocate", "badges": { "location": "France → Canada → Switzerland", @@ -51,25 +51,27 @@ "para3": "Diving into Linux, the FLOSS philosophy, self-hosting various services, and gradually extricating myself from the walled gardens of Big Tech. The more I learned about centralized systems and the organizations behind them, the more I developed a passion for their alternatives.", "para4": "After 4 years in Canada, I'm now heading to Switzerland — bringing my passion for decentralized, permissionless, and privacy-preserving technologies with me.", "para5": "Career-wise, following 10 years in web development, I'm working on shifting towards cybersecurity, with a strong interest in penetration testing.", - "current": "Currently focused on: building AnyMaps and its decentralized infrastructure, contributing to the ecosystems powering my work, getting into cybersecurity, and breaking things to see how they work :)" + "current": "Currently focused on: Getting into cybersecurity, building AnyMaps and its decentralized infrastructure, contributing to the ecosystems powering my work and breaking things to see how they work :)" }, "gpgLabel": "GPG Fingerprint", "copyToast": "GPG fingerprint copied to clipboard" }, "Contact": { "title": "Get in Touch", - "subtitle": "Find me on the web", + "subtitle": "Feel free to reach out for collaboration, questions, or just to say hi!", + "socialSection": "Social", + "directSection": "Direct Contact", "links": { "github": "GitHub", "twitter": "Twitter/X", "linkedin": "LinkedIn", "bluesky": "BlueSky", + "telegram": "Telegram", "matrix": "Matrix", "email": "Email" }, "copyToast": "Copied to clipboard", - "copyLabel": "Copy to clipboard", - "note": "Feel free to reach out for collaboration, questions, or just to say hi!" + "copyLabel": "Copy to clipboard" }, "Terminal": { "unknownCmdErr": "command not recognized", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index 976772c..c7b2d01 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -35,7 +35,7 @@ "andItsUI": "et sa lib UI !" }, "AboutMe": { - "name": "Xav [nipsysdev]", + "name": "Xav [nipsys]", "tagline": "cypherpunk / développeur / défenseur de la souveraineté numérique", "badges": { "location": "France → Canada → Suisse", @@ -51,25 +51,27 @@ "para3": "Plonger dans Linux, la philosophie FLOSS, l'auto-hébergement de divers services, et progressivement m'extraire des \"walled gardens\" de la Big Tech. Plus j'apprenais sur les systèmes centralisés et les organisations qui les contrôlent, plus je suis devenu passioné par leurs alternatives.", "para4": "Après 4 ans au Canada, je m'installe maintenant en Suisse — emportant avec moi ma passion pour les technologies décentralisées, \"permissionless\" et respectueuses de la vie privée.", "para5": "Côté carrière, après 10 ans en développement web, je me forme pour transitionner vers la cybersécurité, avec un fort intérêt pour le pentesting.", - "current": "Ce que je fais actuellement : Développement d'AnyMaps et de son infrastructure décentralisée, contribution aux écosystèmes qui alimentent mes projets, formation en cybersécurité, et mes expérimentations routinières :)" + "current": "Ce que je fais actuellement : Me former en cybersécurité, développer AnyMaps et de son infrastructure décentralisée, contribuer aux écosystèmes qui alimentent mes projets, et mes expérimentations routinières :)" }, "gpgLabel": "Empreinte GPG", "copyToast": "Empreinte GPG copiée dans le presse-papier" }, "Contact": { "title": "Me contacter", - "subtitle": "Retrouvez-moi sur le web", + "subtitle": "N'hésitez pas à me contacter pour collaborer, poser des questions, ou juste pour dire salut !", + "socialSection": "Réseaux sociaux", + "directSection": "Contact direct", "links": { "github": "GitHub", "twitter": "Twitter/X", "linkedin": "LinkedIn", "bluesky": "BlueSky", + "telegram": "Telegram", "matrix": "Matrix", "email": "Courriel" }, "copyToast": "Copié dans le presse-papier", - "copyLabel": "Copier dans le presse-papier", - "note": "N'hésitez pas à me contacter pour collaborer, poser des questions, ou juste pour dire salut !" + "copyLabel": "Copier dans le presse-papier" }, "Terminal": { "unknownCmdErr": "commande non reconnue", From c52248e40e22c040a458b325defb915026d149ca Mon Sep 17 00:00:00 2001 From: Xavier Saliniere Date: Thu, 28 May 2026 02:50:42 -0400 Subject: [PATCH 3/3] refactor: rename services to status across codebase --- .../[locale]/{services => status}/page.tsx | 12 ++++----- .../{ServicesOutput.tsx => StatusOutput.tsx} | 25 +++++++++++-------- src/constants/commands.ts | 6 ++--- src/constants/routes.ts | 2 +- src/i18n/messages/en.json | 7 +++--- src/i18n/messages/fr.json | 7 +++--- src/lib/dpulse/utils/status.ts | 6 ++--- src/types/terminal.ts | 2 +- 8 files changed, 37 insertions(+), 30 deletions(-) rename src/app/[locale]/{services => status}/page.tsx (67%) rename src/components/cmd-outputs/{ServicesOutput.tsx => StatusOutput.tsx} (87%) diff --git a/src/app/[locale]/services/page.tsx b/src/app/[locale]/status/page.tsx similarity index 67% rename from src/app/[locale]/services/page.tsx rename to src/app/[locale]/status/page.tsx index 411b750..52922c6 100644 --- a/src/app/[locale]/services/page.tsx +++ b/src/app/[locale]/status/page.tsx @@ -5,14 +5,14 @@ import type { RouteData } from '@/types/routing'; import { Command } from '@/types/terminal'; import { setPageMeta } from '@/utils/metadata-utils'; -interface ServicesPageProps { +interface StatusPageProps { params: Promise<{ locale: string }>; } export const generateMetadata = async (routeData: RouteData) => - await setPageMeta(routeData, 'services'); + await setPageMeta(routeData, 'status'); -export default async function ServicesPage({ params }: ServicesPageProps) { +export default async function StatusPage({ params }: StatusPageProps) { const { locale } = await params; const t = await getTranslations({ locale, namespace: 'Terminal' }); @@ -20,11 +20,11 @@ export default async function ServicesPage({ params }: ServicesPageProps) { <>
-

{t('cmds.services.title')}

-

{t('cmds.services.description')}

+

{t('cmds.status.title')}

+

{t('cmds.status.description')}

- + ); } diff --git a/src/components/cmd-outputs/ServicesOutput.tsx b/src/components/cmd-outputs/StatusOutput.tsx similarity index 87% rename from src/components/cmd-outputs/ServicesOutput.tsx rename to src/components/cmd-outputs/StatusOutput.tsx index f1f2ae6..7ff1f0c 100644 --- a/src/components/cmd-outputs/ServicesOutput.tsx +++ b/src/components/cmd-outputs/StatusOutput.tsx @@ -72,13 +72,13 @@ function ServiceCard({ statusMsg, t, dayjs }: ServiceCardProps) { variant="body1" style={{ color: 'var(--lsd-text-secondary)' }} > - {statusMsg?.description || `${t('cmds.services.noStatusMessage')}`} + {statusMsg?.description || `${t('cmds.status.noStatusMessage')}`}
- {t('cmds.services.lastChecked')}{' '} + {t('cmds.status.lastChecked')}{' '} {dayjs(statusMsg.timestamp).fromNow()}
@@ -88,7 +88,7 @@ function ServiceCard({ statusMsg, t, dayjs }: ServiceCardProps) { ); } -export default function ServicesOutput({ t }: CommandOutputProps) { +export default function StatusOutput({ t }: CommandOutputProps) { const statusMessages = useStore($statusMessages); const isLoading = useStore($isLoading); const dayjs = useDayjs(); @@ -120,14 +120,19 @@ export default function ServicesOutput({ t }: CommandOutputProps) { return (
- {t('cmds.services.title')} +
+ {t('cmds.status.title')} + + {t('cmds.status.subtitle')} + +
{isWaitingForHeartbeats ? (
{isLoading - ? t('cmds.services.loading') - : t('cmds.services.waitingForHeartbeats')} + ? t('cmds.status.loading') + : t('cmds.status.waitingForHeartbeats')}
) : ( @@ -149,7 +154,7 @@ export default function ServicesOutput({ t }: CommandOutputProps) {
- {t('cmds.services.healthcheckPrefix')}{' '} + {t('cmds.status.healthcheckPrefix')}{' '} - {t('cmds.services.healthcheckSuffix')} + {t('cmds.status.healthcheckSuffix')} dpulse{' '} - {t('cmds.services.dpulseSignsPrefix')}{' '} + {t('cmds.status.dpulseSignsPrefix')}{' '} - {t('cmds.services.logosDeliverySuffix')} + {t('cmds.status.logosDeliverySuffix')}
diff --git a/src/constants/commands.ts b/src/constants/commands.ts index 01050a2..b6cf07f 100644 --- a/src/constants/commands.ts +++ b/src/constants/commands.ts @@ -1,7 +1,7 @@ import BuildInfoOutput from '@/components/cmd-outputs/BuildInfoOutput'; import ContactOutput from '@/components/cmd-outputs/ContactOutput'; import HelpOutput from '@/components/cmd-outputs/HelpOutput'; -import ServicesOutput from '@/components/cmd-outputs/ServicesOutput'; +import StatusOutput from '@/components/cmd-outputs/StatusOutput'; import WelcomeOutput from '@/components/cmd-outputs/WelcomeOutput'; import WhoamiOutput from '@/components/cmd-outputs/WhoamiOutput'; import { Command, type CommandInfo } from '@/types/terminal'; @@ -24,8 +24,8 @@ export const Commands: CommandInfo[] = [ output: ContactOutput, }, { - name: Command.Services, - output: ServicesOutput, + name: Command.Status, + output: StatusOutput, }, { name: Command.Clear, diff --git a/src/constants/routes.ts b/src/constants/routes.ts index ae41cf6..9db057e 100644 --- a/src/constants/routes.ts +++ b/src/constants/routes.ts @@ -1,6 +1,6 @@ export const Routes = { welcome: '/', whoami: '/whoami', - services: '/services', + status: '/status', contact: '/contact', }; diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 954c30f..db95f15 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -15,7 +15,7 @@ "Pages": { "welcome": "welcome", "whoami": "whoami", - "services": "services", + "status": "status", "contact": "contact" }, "Status": { @@ -104,9 +104,10 @@ "whoami": { "description": "Allow me to introduce myself" }, - "services": { + "status": { "description": "Display my self-hosted services status", - "title": "Services that I proudly self-host", + "title": "Status", + "subtitle": "Status of the services that I proudly self-host", "connectionStatus": "Connection Status", "loading": "(Loading...)", "waitingForHeartbeats": "Waiting for heartbeats...", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index c7b2d01..d737577 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -15,7 +15,7 @@ "Pages": { "welcome": "bienvenue", "whoami": "qui suis-je", - "services": "services", + "status": "statut", "contact": "contact" }, "Status": { @@ -104,9 +104,10 @@ "whoami": { "description": "Permettez-moi de me présenter" }, - "services": { + "status": { "description": "Afficher l'état de mes services auto-hébergés", - "title": "Services que j'héberge avec fierté", + "title": "Statut", + "subtitle": "Statut des services que je suis fier d'héberger", "connectionStatus": "État de la connexion", "loading": "(Chargement...)", "waitingForHeartbeats": "En attente de heartbeats...", diff --git a/src/lib/dpulse/utils/status.ts b/src/lib/dpulse/utils/status.ts index a84e816..c6f1680 100644 --- a/src/lib/dpulse/utils/status.ts +++ b/src/lib/dpulse/utils/status.ts @@ -12,19 +12,19 @@ export const STATUS_META = { healthy: { variant: 'success' as const, icon: CheckCircleIcon, - textKey: 'cmds.services.status.healthy', + textKey: 'cmds.status.status.healthy', className: '', }, degraded: { variant: 'warning' as const, icon: CircleNotchIcon, - textKey: 'cmds.services.status.degraded', + textKey: 'cmds.status.status.degraded', className: 'animate-spin', }, down: { variant: 'destructive' as const, icon: XCircleIcon, - textKey: 'cmds.services.status.down', + textKey: 'cmds.status.status.down', className: '', }, }; diff --git a/src/types/terminal.ts b/src/types/terminal.ts index c7a838f..102c477 100644 --- a/src/types/terminal.ts +++ b/src/types/terminal.ts @@ -6,7 +6,7 @@ export enum Command { Clear = 'clear', Contact = 'contact', Help = 'help', - Services = 'services', + Status = 'status', Welcome = 'welcome', Whoami = 'whoami', }