{"version":1,"id":"system-status-page","framework":"next","kind":"block","files":[{"path":"src/blocks/gfa/system-status-page.tsx","content":"\"use client\";\n\nimport {\n  SYSTEM_INCIDENT_STATUS_LABELS,\n  SYSTEM_STATUS_LABELS,\n  buildDemoSystemStatusSnapshot,\n  type PublicSystemIncident,\n  type PublicSystemStatusSnapshot,\n  type SystemComponentStatus,\n  type SystemDayStatus,\n} from \"@/blocks/gfa/system-status-page-data\";\n\nconst BAR: Record<SystemDayStatus, string> = {\n  OPERATIONAL: \"bg-[#22c55e]\",\n  DEGRADED: \"bg-[#eab308]\",\n  PARTIAL_OUTAGE: \"bg-[#f97316]\",\n  MAJOR_OUTAGE: \"bg-[#ef4444]\",\n  MAINTENANCE: \"bg-[#38bdf8]\",\n  NONE: \"bg-[#e5e5ea]\",\n};\n\nconst STATUS_TEXT: Record<SystemComponentStatus, string> = {\n  OPERATIONAL: \"text-[#16a34a]\",\n  DEGRADED: \"text-[#ca8a04]\",\n  PARTIAL_OUTAGE: \"text-[#ea580c]\",\n  MAJOR_OUTAGE: \"text-[#dc2626]\",\n  MAINTENANCE: \"text-[#0284c7]\",\n};\n\nconst BANNER: Record<SystemComponentStatus, string> = {\n  OPERATIONAL: \"bg-[#22c55e] text-white\",\n  DEGRADED: \"bg-[#eab308] text-[#1d1d1f]\",\n  PARTIAL_OUTAGE: \"bg-[#f97316] text-white\",\n  MAJOR_OUTAGE: \"bg-[#ef4444] text-white\",\n  MAINTENANCE: \"bg-[#0ea5e9] text-white\",\n};\n\nfunction formatTime(value: string) {\n  return new Intl.DateTimeFormat(\"en-US\", {\n    timeZone: \"UTC\",\n    day: \"numeric\",\n    month: \"short\",\n    hour: \"2-digit\",\n    minute: \"2-digit\",\n  }).format(new Date(value));\n}\n\nfunction formatUptime(value: number) {\n  return `${value.toLocaleString(\"en-US\", {\n    minimumFractionDigits: value >= 100 ? 0 : 2,\n    maximumFractionDigits: 2,\n  })}% uptime`;\n}\n\nfunction dayLabel(status: SystemDayStatus) {\n  if (status === \"NONE\") return \"No data for this day\";\n  return SYSTEM_STATUS_LABELS[status];\n}\n\nfunction IncidentBlock({ incident }: { incident: PublicSystemIncident }) {\n  return (\n    <article className=\"mt-4\">\n      <h3 className=\"text-[15px] font-semibold text-[#1d1d1f]\">{incident.title}</h3>\n      <ol className=\"mt-3 space-y-3 border-l border-[#eaeaea] pl-4\">\n        {incident.updates.map((update) => (\n          <li key={update.id}>\n            <p className=\"text-[13px] leading-relaxed text-[#444]\">\n              <span className=\"font-semibold text-[#1d1d1f]\">\n                {SYSTEM_INCIDENT_STATUS_LABELS[update.status]}\n              </span>\n              {\" — \"}\n              {update.message}\n            </p>\n            <p className=\"mt-1 text-[12px] text-[#86868b]\">{formatTime(update.createdAt)}</p>\n          </li>\n        ))}\n      </ol>\n    </article>\n  );\n}\n\nexport type SystemStatusPageProps = {\n  /** Live or custom snapshot. Defaults to built-in demo data. */\n  snapshot?: PublicSystemStatusSnapshot;\n};\n\n/** Statuspage-style public system status (uptime bars + incidents). */\nexport function SystemStatusPage({ snapshot }: SystemStatusPageProps) {\n  const data = snapshot ?? buildDemoSystemStatusSnapshot();\n\n  return (\n    <div className=\"bg-white text-[#1d1d1f]\">\n      <div className=\"mx-auto w-full max-w-[920px] px-4 pb-16 pt-6 sm:px-6 sm:pb-24 sm:pt-10\">\n        <div className=\"flex items-start justify-between gap-4\">\n          <div>\n            <p className=\"text-[13px] text-[#86868b]\">\n              <span>Home</span>\n              <span aria-hidden> / </span>\n              System status\n            </p>\n            <h1 className=\"mt-2 text-[22px] font-semibold tracking-tight text-[#1d1d1f] sm:text-[28px]\">\n              Status\n            </h1>\n          </div>\n        </div>\n\n        <div\n          className={`mt-6 flex min-h-14 items-center rounded-[10px] px-4 py-3 text-[16px] font-semibold sm:px-5 sm:text-[18px] ${BANNER[data.overall]}`}\n        >\n          {data.overallLabel}\n        </div>\n\n        <p className=\"mt-6 text-[13px] text-[#86868b]\">Uptime over the last 90 days.</p>\n\n        <section className=\"mt-4 divide-y divide-[#ececee] border-y border-[#ececee]\">\n          {data.components.map((component) => (\n            <div key={component.id} className=\"py-5\">\n              <div className=\"flex items-baseline justify-between gap-3\">\n                <h2 className=\"text-[14px] font-medium text-[#1d1d1f] sm:text-[15px]\">\n                  {component.name}\n                </h2>\n                <p className={`text-[13px] font-medium ${STATUS_TEXT[component.status]}`}>\n                  {SYSTEM_STATUS_LABELS[component.status]}\n                </p>\n              </div>\n\n              <div\n                className=\"mt-3 flex h-8 gap-px sm:h-9\"\n                role=\"img\"\n                aria-label={`${component.name} 90-day uptime`}\n              >\n                {component.history.map((day, index) => (\n                  <span\n                    key={`${component.id}-${index}`}\n                    title={dayLabel(day)}\n                    className={`min-w-0 flex-1 rounded-[1px] ${BAR[day]}`}\n                  />\n                ))}\n              </div>\n\n              <div className=\"mt-2 flex items-center justify-between text-[11px] text-[#86868b] sm:text-[12px]\">\n                <span>90 days ago</span>\n                <span>{formatUptime(component.uptimePercent)}</span>\n                <span>Today</span>\n              </div>\n            </div>\n          ))}\n        </section>\n\n        <ul className=\"mt-6 flex flex-wrap gap-x-4 gap-y-2 text-[12px] text-[#666]\">\n          {(\n            [\n              [\"OPERATIONAL\", \"Operational\"],\n              [\"DEGRADED\", \"Degraded\"],\n              [\"PARTIAL_OUTAGE\", \"Partial outage\"],\n              [\"MAJOR_OUTAGE\", \"Major outage\"],\n              [\"MAINTENANCE\", \"Maintenance\"],\n            ] as const\n          ).map(([status, label]) => (\n            <li key={status} className=\"inline-flex items-center gap-1.5\">\n              <span className={`h-2.5 w-2.5 rounded-[2px] ${BAR[status]}`} />\n              {label}\n            </li>\n          ))}\n        </ul>\n\n        {data.activeIncidents.length > 0 ? (\n          <section className=\"mt-12\">\n            <h2 className=\"text-[18px] font-semibold tracking-tight text-[#1d1d1f]\">\n              Active incidents\n            </h2>\n            <div className=\"mt-4 divide-y divide-[#ececee] border-t border-[#ececee]\">\n              {data.activeIncidents.map((incident) => (\n                <div key={incident.id} className=\"py-5\">\n                  <IncidentBlock incident={incident} />\n                </div>\n              ))}\n            </div>\n          </section>\n        ) : null}\n\n        <section className=\"mt-12\">\n          <h2 className=\"text-[18px] font-semibold tracking-tight text-[#1d1d1f]\">\n            Past incidents\n          </h2>\n          <div className=\"mt-4 divide-y divide-[#ececee] border-t border-[#ececee]\">\n            {data.pastDays.map((day) => (\n              <div key={day.date} className=\"py-5\">\n                <h3 className=\"text-[14px] font-semibold capitalize text-[#1d1d1f]\">\n                  {day.label}\n                </h3>\n                {day.incidents.length === 0 ? (\n                  <p className=\"mt-2 text-[13px] text-[#86868b]\">No incidents reported.</p>\n                ) : (\n                  day.incidents.map((incident) => (\n                    <IncidentBlock key={incident.id} incident={incident} />\n                  ))\n                )}\n              </div>\n            ))}\n          </div>\n        </section>\n      </div>\n    </div>\n  );\n}\n"},{"path":"src/blocks/gfa/system-status-page-data.ts","content":"export const SYSTEM_COMPONENT_STATUSES = [\n  \"OPERATIONAL\",\n  \"DEGRADED\",\n  \"PARTIAL_OUTAGE\",\n  \"MAJOR_OUTAGE\",\n  \"MAINTENANCE\",\n] as const;\n\nexport type SystemComponentStatus = (typeof SYSTEM_COMPONENT_STATUSES)[number];\n\nexport type SystemDayStatus = SystemComponentStatus | \"NONE\";\n\nexport const SYSTEM_STATUS_LABELS: Record<SystemComponentStatus, string> = {\n  OPERATIONAL: \"Operational\",\n  DEGRADED: \"Degraded\",\n  PARTIAL_OUTAGE: \"Partial outage\",\n  MAJOR_OUTAGE: \"Major outage\",\n  MAINTENANCE: \"Maintenance\",\n};\n\nexport const SYSTEM_OVERALL_LABELS: Record<SystemComponentStatus, string> = {\n  OPERATIONAL: \"All Systems Operational\",\n  DEGRADED: \"Degraded Performance\",\n  PARTIAL_OUTAGE: \"Partial Outage\",\n  MAJOR_OUTAGE: \"Major Outage\",\n  MAINTENANCE: \"Scheduled Maintenance\",\n};\n\nexport const SYSTEM_INCIDENT_STATUS_LABELS = {\n  INVESTIGATING: \"Investigating\",\n  IDENTIFIED: \"Identified\",\n  MONITORING: \"Monitoring\",\n  RESOLVED: \"Resolved\",\n} as const;\n\nexport type SystemIncidentStatus = keyof typeof SYSTEM_INCIDENT_STATUS_LABELS;\n\nexport type PublicSystemIncidentUpdate = {\n  id: string;\n  status: SystemIncidentStatus;\n  message: string;\n  createdAt: string;\n};\n\nexport type PublicSystemIncident = {\n  id: string;\n  title: string;\n  severity: \"MINOR\" | \"MAJOR\" | \"CRITICAL\";\n  status: SystemIncidentStatus;\n  startedAt: string;\n  resolvedAt: string | null;\n  updates: PublicSystemIncidentUpdate[];\n};\n\nexport type PublicSystemComponent = {\n  id: string;\n  key: string;\n  name: string;\n  description: string | null;\n  status: SystemComponentStatus;\n  history: SystemDayStatus[];\n  uptimePercent: number;\n};\n\nexport type PublicStatusDay = {\n  date: string;\n  label: string;\n  incidents: PublicSystemIncident[];\n};\n\nexport type PublicSystemStatusSnapshot = {\n  overall: SystemComponentStatus;\n  overallLabel: string;\n  checkedAt: string;\n  components: PublicSystemComponent[];\n  activeIncidents: PublicSystemIncident[];\n  pastDays: PublicStatusDay[];\n};\n\nfunction utcYmd(date: Date) {\n  return new Intl.DateTimeFormat(\"en-CA\", {\n    timeZone: \"UTC\",\n    year: \"numeric\",\n    month: \"2-digit\",\n    day: \"2-digit\",\n  }).format(date);\n}\n\nfunction formatDayHeading(ymd: string) {\n  return new Intl.DateTimeFormat(\"en-US\", {\n    timeZone: \"UTC\",\n    weekday: \"long\",\n    day: \"numeric\",\n    month: \"long\",\n    year: \"numeric\",\n  }).format(new Date(`${ymd}T12:00:00Z`));\n}\n\nfunction historyDates(days: number) {\n  const out: string[] = [];\n  const now = new Date();\n  for (let i = days - 1; i >= 0; i -= 1) {\n    const d = new Date(now);\n    d.setUTCDate(now.getUTCDate() - i);\n    out.push(utcYmd(d));\n  }\n  return out;\n}\n\nfunction seededStatus(seed: number): SystemDayStatus {\n  const n = seed % 97;\n  if (n === 11) return \"DEGRADED\";\n  if (n === 23) return \"PARTIAL_OUTAGE\";\n  if (n === 41) return \"MAINTENANCE\";\n  if (n === 67) return \"MAJOR_OUTAGE\";\n  return \"OPERATIONAL\";\n}\n\nfunction buildHistory(seedBase: number, days: string[]): {\n  history: SystemDayStatus[];\n  uptimePercent: number;\n} {\n  const history = days.map((day, index) => {\n    const seed = seedBase * 17 + index * 13 + day.length * 3;\n    return seededStatus(seed);\n  });\n  const up =\n    history.filter((d) => d === \"OPERATIONAL\" || d === \"NONE\").length /\n    Math.max(history.length, 1);\n  return {\n    history,\n    uptimePercent: Math.round(up * 10000) / 100,\n  };\n}\n\n/** Demo snapshot matching Ecomos /sistem-durumu shape (English UI). */\nexport function buildDemoSystemStatusSnapshot(): PublicSystemStatusSnapshot {\n  const days = historyDates(90);\n  const calendar = days.slice(-14);\n  const componentsSpec = [\n    { id: \"c1\", key: \"storefront\", name: \"Storefront\", seed: 3, status: \"OPERATIONAL\" as const },\n    { id: \"c2\", key: \"api\", name: \"API\", seed: 7, status: \"OPERATIONAL\" as const },\n    { id: \"c3\", key: \"database\", name: \"Database\", seed: 11, status: \"OPERATIONAL\" as const },\n    { id: \"c4\", key: \"cache\", name: \"Cache\", seed: 13, status: \"DEGRADED\" as const },\n    { id: \"c5\", key: \"checkout\", name: \"Checkout & orders\", seed: 17, status: \"OPERATIONAL\" as const },\n    { id: \"c6\", key: \"auth\", name: \"Sign-in & accounts\", seed: 19, status: \"OPERATIONAL\" as const },\n    { id: \"c7\", key: \"search\", name: \"Search & discovery\", seed: 23, status: \"OPERATIONAL\" as const },\n  ];\n\n  const components = componentsSpec.map((item) => {\n    const { history, uptimePercent } = buildHistory(item.seed, days);\n    history[history.length - 1] = item.status;\n    return {\n      id: item.id,\n      key: item.key,\n      name: item.name,\n      description: null,\n      status: item.status,\n      history,\n      uptimePercent,\n    };\n  });\n\n  const overall: SystemComponentStatus = components.some((c) => c.status === \"DEGRADED\")\n    ? \"DEGRADED\"\n    : \"OPERATIONAL\";\n\n  const pastIncident: PublicSystemIncident = {\n    id: \"inc-1\",\n    title: \"Elevated latency on the cache layer\",\n    severity: \"MINOR\",\n    status: \"RESOLVED\",\n    startedAt: new Date(Date.now() - 1000 * 60 * 60 * 30).toISOString(),\n    resolvedAt: new Date(Date.now() - 1000 * 60 * 60 * 26).toISOString(),\n    updates: [\n      {\n        id: \"u1\",\n        status: \"INVESTIGATING\",\n        message: \"Increased Redis response times were observed.\",\n        createdAt: new Date(Date.now() - 1000 * 60 * 60 * 30).toISOString(),\n      },\n      {\n        id: \"u2\",\n        status: \"IDENTIFIED\",\n        message: \"The connection pool limit was reached.\",\n        createdAt: new Date(Date.now() - 1000 * 60 * 60 * 28).toISOString(),\n      },\n      {\n        id: \"u3\",\n        status: \"RESOLVED\",\n        message: \"Pool size was increased and service returned to normal.\",\n        createdAt: new Date(Date.now() - 1000 * 60 * 60 * 26).toISOString(),\n      },\n    ],\n  };\n\n  const incidentDay = utcYmd(new Date(pastIncident.startedAt));\n\n  return {\n    overall,\n    overallLabel: SYSTEM_OVERALL_LABELS[overall],\n    checkedAt: new Date().toISOString(),\n    components,\n    activeIncidents: [],\n    pastDays: [...calendar].reverse().map((date) => ({\n      date,\n      label: formatDayHeading(date),\n      incidents: date === incidentDay ? [pastIncident] : [],\n    })),\n  };\n}\n"}],"meta":{"studioName":"GFA Development & Design Studio","siteUrl":"https://ui.gkhn.dev"}}