This is an automated email from the ASF dual-hosted git repository.

pawarprasad123 pushed a commit to branch feature/pr-9-License-added-forNewfile
in repository https://gitbox.apache.org/repos/asf/atlas.git

commit 6d04263be68593b245bc45e2e4ec937aa624612a
Author: Prasad Pawar <[email protected]>
AuthorDate: Fri May 8 12:59:40 2026 +0530

    ATLAS-5247, ATLAS-5248, ATLAS-5249, ATLAS-5250, ATLAS-5252, ATLAS-5254, 
ATLAS-5255: ATLAS UI: Dashboard All cards. (#620)
---
 dashboard/src/utils/metricsUtils.ts                | 241 ++++++++++++
 dashboard/src/utils/typeCatalogUtils.ts            | 159 ++++++++
 dashboard/src/views/DashBoard.tsx                  |  83 ++---
 .../DashboardOverview/ClassificationCoverage.tsx   | 394 ++++++++++++++++++++
 .../ClassificationDistributionCard.tsx             | 227 ++++++++++++
 .../views/DashboardOverview/DashboardOverview.tsx  | 149 ++++++++
 .../views/DashboardOverview/DashboardSkeleton.tsx  |  39 ++
 .../views/DashboardOverview/EntityStatusDonut.tsx  | 173 +++++++++
 .../views/DashboardOverview/EntityTypeBarChart.tsx | 327 +++++++++++++++++
 .../EntityTypeBarChartSkeleton.tsx                 |  57 +++
 .../DashboardOverview/KafkaTopicSummaryCard.tsx    | 402 ++++++++++++++++++++
 .../DashboardOverview/MessageConsumptionChart.tsx  | 257 +++++++++++++
 .../src/views/DashboardOverview/OverviewCard.tsx   | 114 ++++++
 .../src/views/DashboardOverview/RecentActivity.tsx | 408 +++++++++++++++++++++
 .../DashboardOverview/RecentActivitySkeleton.tsx   |  37 ++
 .../DashboardOverview/dashboardChartPalette.ts     |  42 +++
 16 files changed, 3055 insertions(+), 54 deletions(-)

diff --git a/dashboard/src/utils/metricsUtils.ts 
b/dashboard/src/utils/metricsUtils.ts
new file mode 100644
index 000000000..2b6b6bcf2
--- /dev/null
+++ b/dashboard/src/utils/metricsUtils.ts
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export const sumEntityMetrics = (obj: Record<string, number> | undefined): 
number =>
+       Object.values(obj || {}).reduce((a, b) => a + (Number(b) || 0), 0);
+
+export const getEntityStatusTotals = (entity: Record<string, unknown> | 
undefined) => ({
+       active: sumEntityMetrics(entity?.entityActive as Record<string, 
number>),
+       shell: sumEntityMetrics(entity?.entityShell as Record<string, number>),
+       deleted: sumEntityMetrics(entity?.entityDeleted as Record<string, 
number>)
+});
+
+export interface EntityTypeDistributionItem {
+       name: string;
+       count: number;
+       active: number;
+       deleted: number;
+       /** Entity typedef names rolled into this bar (e.g. service type 
buckets). */
+       underlyingTypeNames?: string[];
+}
+
+export const getTaggedCount = (tag: Record<string, unknown> | undefined): 
number =>
+       sumEntityMetrics(tag?.tagEntities as Record<string, number>);
+
+/** tagEntities values summed — counts tag–entity associations, not unique 
entities */
+export const getTagEntityAssociationTotal = (tag: Record<string, unknown> | 
undefined): number =>
+       getTaggedCount(tag);
+
+/**
+ * Number of classification types that have at least one active entity (each 
key in
+ * tagEntities with count > 0). Does not double-count the same entity across 
types.
+ */
+export const getClassificationTypesInUseCount = (tag: Record<string, unknown> 
| undefined): number => {
+       const tagEntities = tag?.tagEntities as Record<string, number> | 
undefined;
+       if (!tagEntities || typeof tagEntities !== "object") return 0;
+       return Object.values(tagEntities).filter((c) => (Number(c) || 0) > 
0).length;
+};
+
+/** Classification names that have at least one entity assignment per tag 
metrics. */
+export const getClassificationNamesInUseFromTag = (
+       tag: Record<string, unknown> | undefined
+): Set<string> => {
+       const tagEntities = tag?.tagEntities as Record<string, number> | 
undefined;
+       const names = new Set<string>();
+       if (!tagEntities || typeof tagEntities !== "object") return names;
+       for (const [name, count] of Object.entries(tagEntities)) {
+               if ((Number(count) || 0) > 0) {
+                       names.add(name);
+               }
+       }
+       return names;
+};
+
+/**
+ * Defined classification names (from type defs) with no entity assignments in 
metrics.
+ */
+export const getUnusedClassificationNames = (
+       definedNames: string[],
+       tag: Record<string, unknown> | undefined
+): string[] => {
+       const inUse = getClassificationNamesInUseFromTag(tag);
+       return definedNames.filter((n) => !inUse.has(n)).sort((a, b) => 
a.localeCompare(b));
+};
+
+/** Parse stats from metrics general.stats (keys like 
"Notification:currentDay" -> { Notification: { currentDay } }) */
+export const parseMetricsStats = (stats: Record<string, unknown> | undefined): 
Record<string, Record<string, unknown>> => {
+       const result: Record<string, Record<string, unknown>> = {};
+       if (!stats || typeof stats !== "object") return result;
+       for (const key of Object.keys(stats)) {
+               const parts = key.split(":");
+               const group = parts[0];
+               const subKey = parts[1];
+               if (!group || !subKey) continue;
+               if (!result[group]) result[group] = {};
+               result[group][subKey] = stats[key];
+       }
+       return result;
+};
+
+export interface MessageConsumptionItem {
+       period: string;
+       count: number;
+       creates: number;
+       updates: number;
+       deletes: number;
+       failed: number;
+       avgTime: number;
+}
+
+const getNotificationValue = (
+       notification: Record<string, unknown>,
+       key: string,
+       field: "creates" | "updates" | "deletes" | "failed" | "avgTime"
+): number => {
+       const keyMap: Record<string, Record<string, string>> = {
+               total: { creates: "totalCreates", updates: "totalUpdates", 
deletes: "totalDeletes", failed: "totalFailed", avgTime: "totalAvgTime" },
+               currentHour: { creates: "currentHourEntityCreates", updates: 
"currentHourEntityUpdates", deletes: "currentHourEntityDeletes", failed: 
"currentHourFailed", avgTime: "currentHourAvgTime" },
+               previousHour: { creates: "previousHourEntityCreates", updates: 
"previousHourEntityUpdates", deletes: "previousHourEntityDeletes", failed: 
"previousHourFailed", avgTime: "previousHourAvgTime" },
+               currentDay: { creates: "currentDayEntityCreates", updates: 
"currentDayEntityUpdates", deletes: "currentDayEntityDeletes", failed: 
"currentDayFailed", avgTime: "currentDayAvgTime" },
+               previousDay: { creates: "previousDayEntityCreates", updates: 
"previousDayEntityUpdates", deletes: "previousDayEntityDeletes", failed: 
"previousDayFailed", avgTime: "previousDayAvgTime" }
+       };
+       const fullKey = keyMap[key]?.[field] ?? "";
+       return Number(notification[fullKey] ?? 0);
+};
+
+export interface GetMessageConsumptionDataOptions {
+       /** When false, omits the Total period (e.g. topic rows where total is 
shown as Processed). */
+       includeTotal?: boolean;
+}
+
+/** Extract message consumption data for bar chart from Notification stats */
+export const getMessageConsumptionData = (
+       notification: Record<string, unknown> | undefined,
+       options?: GetMessageConsumptionDataOptions
+): MessageConsumptionItem[] => {
+       if (!notification) return [];
+       const includeTotal = options?.includeTotal !== false;
+       const periods = [
+               { key: "total", label: "Total" },
+               { key: "currentHour", label: "Current Hour" },
+               { key: "previousHour", label: "Previous Hour" },
+               { key: "currentDay", label: "Current Day" },
+               { key: "previousDay", label: "Previous Day" }
+       ];
+       const selected = includeTotal ? periods : periods.filter((p) => p.key 
!== "total");
+       return selected.map(({ key, label }) => ({
+               period: label,
+               count: Number(notification[key] ?? 0),
+               creates: getNotificationValue(notification, key, "creates"),
+               updates: getNotificationValue(notification, key, "updates"),
+               deletes: getNotificationValue(notification, key, "deletes"),
+               failed: getNotificationValue(notification, key, "failed"),
+               avgTime: getNotificationValue(notification, key, "avgTime")
+       }));
+};
+
+/**
+ * Topic partition maps sometimes repeat `Notification:*` keys from the wire 
format.
+ * Strip the prefix so getMessageConsumptionData finds `currentHour`, 
`totalCreates`, etc.
+ */
+export const normalizeTopicMetricsRecord = (
+       topicDetail: Record<string, unknown> | undefined
+): Record<string, unknown> => {
+       if (!topicDetail || typeof topicDetail !== "object") return {};
+       const out: Record<string, unknown> = { ...topicDetail };
+       for (const key of Object.keys(topicDetail)) {
+               if (!key.startsWith("Notification:")) continue;
+               const shortKey = key.slice("Notification:".length);
+               if (shortKey && out[shortKey] === undefined) {
+                       out[shortKey] = topicDetail[key];
+               }
+       }
+       return out;
+};
+
+/**
+ * True when the payload includes at least one period bucket count (hour/day 
series).
+ * `total` alone is not enough — legacy rows often only mirror 
processedMessageCount.
+ */
+export const topicRowHasPeriodMetrics = (topicDetail: Record<string, unknown> 
| undefined): boolean => {
+       const n = normalizeTopicMetricsRecord(topicDetail);
+       return (
+               n.currentHour !== undefined ||
+               n.previousHour !== undefined ||
+               n.currentDay !== undefined ||
+               n.previousDay !== undefined
+       );
+};
+
+const omitTopicDetailsFromNotification = (
+       notification: Record<string, unknown> | undefined
+): Record<string, unknown> => {
+       if (!notification || typeof notification !== "object") return {};
+       const { topicDetails: _omit, ...rest } = notification;
+       return rest;
+};
+
+/**
+ * One entry from `Notification.topicDetails` for getMessageConsumptionData.
+ * When the server omits per-period fields on partitions (legacy payload), 
merge in
+ * aggregate `Notification` (excluding `topicDetails`) so the chart matches 
/admin/metrics.
+ */
+export const buildTopicNotificationRecord = (
+       topicDetail: Record<string, unknown> | undefined,
+       options?: {
+               aggregateNotification?: Record<string, unknown> | undefined;
+               /** When true, fill period keys from aggregate if the topic row 
lacks them. */
+               useAggregateFallback?: boolean;
+       }
+): Record<string, unknown> | undefined => {
+       if (!topicDetail || typeof topicDetail !== "object") {
+               if (options?.useAggregateFallback && 
options?.aggregateNotification) {
+                       return 
omitTopicDetailsFromNotification(options.aggregateNotification);
+               }
+               return undefined;
+       }
+       const normalized = normalizeTopicMetricsRecord(topicDetail);
+       if (!options?.useAggregateFallback || !options?.aggregateNotification) {
+               return normalized;
+       }
+       const base = 
omitTopicDetailsFromNotification(options.aggregateNotification);
+       return { ...base, ...normalized };
+};
+
+/** Chart periods without Total (Processed column shows the total). */
+export const getMessageConsumptionDataExcludingTotal = (
+       notification: Record<string, unknown> | undefined
+): MessageConsumptionItem[] =>
+       getMessageConsumptionData(notification, { includeTotal: false });
+
+export interface ClassificationDistributionItem {
+       name: string;
+       count: number;
+}
+
+/** Top classifications by entity count from tag.tagEntities */
+export const getClassificationDistribution = (
+       tag: Record<string, unknown> | undefined,
+       topN = 5
+): ClassificationDistributionItem[] => {
+       const tagEntities = tag?.tagEntities as Record<string, number> | 
undefined;
+       if (!tagEntities) return [];
+       return Object.entries(tagEntities)
+               .map(([name, count]) => ({ name, count: Number(count) || 0 }))
+               .sort((a, b) => b.count - a.count)
+               .slice(0, topN);
+};
diff --git a/dashboard/src/utils/typeCatalogUtils.ts 
b/dashboard/src/utils/typeCatalogUtils.ts
new file mode 100644
index 000000000..078a36c79
--- /dev/null
+++ b/dashboard/src/utils/typeCatalogUtils.ts
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { EntityTypeDistributionItem } from "./metricsUtils";
+
+/** Minimal typedef row from `/api/atlas/types/typedefs/headers` (see 
EntitiesTree). */
+export interface TypeHeaderCatalogRow {
+       name: string;
+       category: string;
+       serviceType?: string;
+       guid?: string;
+}
+
+export interface DashboardTypeCatalog {
+       classificationNames: string[];
+       /** Glossary-related entity typedef names (Atlas glossary model). */
+       glossaryTermRelatedTypeNames: string[];
+       businessMetadataNames: string[];
+       /** All ENTITY typedef names (sorted). */
+       entityTypeNames: string[];
+}
+
+const DEFAULT_SERVICE_TYPE = "other_types";
+
+const countForEntityType = (
+       entity: Record<string, unknown> | undefined,
+       typeName: string
+): { active: number; deleted: number } => {
+       const active = (entity?.entityActive as Record<string, number>) || {};
+       const deleted = (entity?.entityDeleted as Record<string, number>) || {};
+       return {
+               active: Number(active[typeName] ?? 0) || 0,
+               deleted: Number(deleted[typeName] ?? 0) || 0,
+       };
+};
+
+/**
+ * Service-type buckets aligned with the Entities sidebar (`serviceType` on 
each ENTITY typedef).
+ * Falls back to `{typeName}_` prefix grouping when headers are missing (e.g. 
hive_table → hive).
+ */
+export const getServiceTypeDistribution = (
+       entity: Record<string, unknown> | undefined,
+       typeHeaders: TypeHeaderCatalogRow[] | null | undefined,
+       topN = 5
+): EntityTypeDistributionItem[] => {
+       const active = (entity?.entityActive as Record<string, number>) || {};
+       const deleted = (entity?.entityDeleted as Record<string, number>) || {};
+       const map = new Map<
+               string,
+               { active: number; deleted: number; typeNames: Set<string> }
+       >();
+
+       const add = (serviceKey: string, typeName: string) => {
+               const { active: a, deleted: d } = countForEntityType(entity, 
typeName);
+               const cur = map.get(serviceKey) ?? {
+                       active: 0,
+                       deleted: 0,
+                       typeNames: new Set<string>(),
+               };
+               cur.active += a;
+               cur.deleted += d;
+               cur.typeNames.add(typeName);
+               map.set(serviceKey, cur);
+       };
+
+       if (Array.isArray(typeHeaders) && typeHeaders.length > 0) {
+               for (const row of typeHeaders) {
+                       if (row.category !== "ENTITY") continue;
+                       const st = (row.serviceType?.trim() || 
DEFAULT_SERVICE_TYPE) as string;
+                       add(st, row.name);
+               }
+       } else {
+               const allTypes = new Set([...Object.keys(active), 
...Object.keys(deleted)]);
+               allTypes.forEach((typeName) => {
+                       const i = typeName.indexOf("_");
+                       const serviceKey = i === -1 ? typeName : 
typeName.slice(0, i);
+                       add(serviceKey, typeName);
+               });
+       }
+
+       const rows: EntityTypeDistributionItem[] = [...map.entries()].map(
+               ([name, { active: a, deleted: d, typeNames }]) => ({
+                       name,
+                       active: a,
+                       deleted: d,
+                       count: a + d,
+                       underlyingTypeNames: [...typeNames].sort(),
+               })
+       );
+
+       rows.sort((x, y) => y.count - x.count || x.name.localeCompare(y.name));
+
+       const top = rows.slice(0, topN);
+       if (top.length === topN) return top;
+
+       const used = new Set(top.map((r) => r.name));
+       const pad = rows
+               .filter((r) => !used.has(r.name))
+               .sort((a, b) => a.name.localeCompare(b.name));
+       while (top.length < topN && pad.length > 0) {
+               const next = pad.shift();
+               if (next) top.push(next);
+       }
+       return top;
+};
+
+/** Lists derived from type headers for search / future features. */
+export const buildDashboardTypeCatalog = (
+       typeHeaders: TypeHeaderCatalogRow[] | null | undefined
+): DashboardTypeCatalog => {
+       const empty: DashboardTypeCatalog = {
+               classificationNames: [],
+               glossaryTermRelatedTypeNames: [],
+               businessMetadataNames: [],
+               entityTypeNames: [],
+       };
+       if (!Array.isArray(typeHeaders) || typeHeaders.length === 0) return 
empty;
+
+       const classificationNames: string[] = [];
+       const businessMetadataNames: string[] = [];
+       const entityTypeNames: string[] = [];
+       const glossaryTermRelatedTypeNames: string[] = [];
+
+       for (const row of typeHeaders) {
+               const { name, category } = row;
+               if (!name) continue;
+               if (category === "CLASSIFICATION") 
classificationNames.push(name);
+               else if (category === "BUSINESS_METADATA") 
businessMetadataNames.push(name);
+               else if (category === "ENTITY") {
+                       entityTypeNames.push(name);
+                       if (name.toLowerCase().includes("glossary")) {
+                               glossaryTermRelatedTypeNames.push(name);
+                       }
+               }
+       }
+
+       const sortUnique = (arr: string[]) => [...new Set(arr)].sort((a, b) => 
a.localeCompare(b));
+
+       return {
+               classificationNames: sortUnique(classificationNames),
+               businessMetadataNames: sortUnique(businessMetadataNames),
+               entityTypeNames: sortUnique(entityTypeNames),
+               glossaryTermRelatedTypeNames: 
sortUnique(glossaryTermRelatedTypeNames),
+       };
+};
diff --git a/dashboard/src/views/DashBoard.tsx 
b/dashboard/src/views/DashBoard.tsx
index 9b8dde430..c0b5a201e 100644
--- a/dashboard/src/views/DashBoard.tsx
+++ b/dashboard/src/views/DashBoard.tsx
@@ -15,65 +15,40 @@
  * limitations under the License.
  */
 
+import { Stack } from "@mui/material";
 import QuickSearch from "@components/GlobalSearch/QuickSearch";
-import { CustomButton } from "@components/muiComponents";
+import DashboardOverview from "./DashboardOverview/DashboardOverview";
 import { useAppSelector } from "@hooks/reducerHook";
-import { Stack } from "@mui/material";
-import { useState } from "react";
-import EntityForm from "./Entity/EntityForm";
-import AddIcon from "@mui/icons-material/Add";
 
 const DashBoard = () => {
-  const { sessionObj = "" }: any = useAppSelector(
-    (state: any) => state.session
-  );
-  const [entityModal, setEntityModal] = useState<boolean>(false);
-  const { data } = sessionObj || {};
-  const key = "atlas.entity.create.allowed";
-  const entityCreate = data?.[key] || "";
+       const dashboardRefreshVersion = useAppSelector((state) => 
state.dashboardRefresh.version);
 
-  const handleOpenEntityModal = () => {
-    setEntityModal(true);
-  };
-  const handleCloseEntityModal = () => {
-    setEntityModal(false);
-  };
-  return (
-    <Stack
-      alignItems="flex-start"
-      justifyContent="space-between"
-      position="relative"
-      height="100%"
-      flex="1"
-      padding="0"
-    >
-      <Stack direction="row" justifyContent="flex-end" width={"100%"}>
-        {entityCreate && (
-          <CustomButton
-            variant="contained"
-            size="small"
-            onClick={(_e: any) => handleOpenEntityModal()}
-            startIcon={<AddIcon />}
-          >
-            Create Entity
-          </CustomButton>
-        )}
-      </Stack>
-      <Stack
-        justifyContent="center"
-        flex="1"
-        alignItems={"center"}
-        height={"100%"}
-        width={"100%"}
-        className="dashboard-quick-search"
-      >
-        <QuickSearch />
-      </Stack>
-      {entityModal && (
-        <EntityForm open={entityModal} onClose={handleCloseEntityModal} />
-      )}
-    </Stack>
-  );
+       return (
+               <Stack
+                       width="100%"
+                       maxWidth="100%"
+                       alignItems="stretch"
+                       justifyContent="flex-start"
+                       position="relative"
+                       height="100%"
+                       flex="1"
+                       padding={0}
+                       spacing={2}
+                       sx={{ boxSizing: "border-box", overflow: "hidden" }}
+               >
+                       <Stack
+                               direction="row"
+                               width="100%"
+                               justifyContent="center"
+                               sx={{ mb: 2, flexShrink: 0 }}
+                       >
+                               <QuickSearch key={dashboardRefreshVersion} />
+                       </Stack>
+                       <Stack width="100%" flex={1} sx={{ minWidth: 0 }}>
+                               <DashboardOverview />
+                       </Stack>
+               </Stack>
+       );
 };
 
 export default DashBoard;
diff --git a/dashboard/src/views/DashboardOverview/ClassificationCoverage.tsx 
b/dashboard/src/views/DashboardOverview/ClassificationCoverage.tsx
new file mode 100644
index 000000000..21fc18588
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/ClassificationCoverage.tsx
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { memo, useCallback, useEffect, useMemo, useState } from "react";
+import {
+       Paper,
+       Stack,
+       Typography,
+       Box,
+       List,
+       ListItem,
+       Link,
+       TextField,
+       InputAdornment,
+} from "@mui/material";
+import SearchIcon from "@mui/icons-material/Search";
+import { Link as RouterLink, useNavigate } from "react-router-dom";
+import CustomModal from "@components/Modal";
+import { numberFormatWithComma } from "@utils/Helper";
+import {
+       getClassificationTypesInUseCount,
+       getUnusedClassificationNames,
+} from "@utils/metricsUtils";
+import { navigateToTaggedSearch } from "@utils/dashboardSearchUtils";
+import { useAppDispatch, useAppSelector } from "@hooks/reducerHook";
+import { fetchClassificationData } from 
"@redux/slice/typeDefSlices/typedefClassificationSlice";
+
+interface ClassificationCoverageProps {
+       /** Defined classification types in the type system (from 
general.tagCount) */
+       classificationTypeDefinitions: number;
+       tag: Record<string, unknown> | undefined;
+       isLoading?: boolean;
+}
+
+const ClassificationCoverage = memo(
+       ({
+               classificationTypeDefinitions,
+               tag,
+               isLoading,
+       }: ClassificationCoverageProps) => {
+               const navigate = useNavigate();
+               const dispatch = useAppDispatch();
+               const { classificationData, loadingClassification } = 
useAppSelector(
+                       (state: { classification?: { classificationData?: { 
classificationDefs?: { name: string }[] } | null; loadingClassification?: 
boolean } }) =>
+                               state.classification ?? {}
+               );
+
+               useEffect(() => {
+                       if (!classificationData && !loadingClassification) {
+                               void dispatch(fetchClassificationData());
+                       }
+               }, [classificationData, loadingClassification, dispatch]);
+
+               const definedNames = useMemo(() => {
+                       const defs =
+                               classificationData?.classificationDefs as { 
name?: string }[] | undefined;
+                       if (!Array.isArray(defs)) return [];
+                       return defs.map((d) => d.name).filter((n): n is string 
=> Boolean(n));
+               }, [classificationData]);
+
+               const typesInUse = useMemo(
+                       () => getClassificationTypesInUseCount(tag),
+                       [tag]
+               );
+               const unusedNames = useMemo(
+                       () => getUnusedClassificationNames(definedNames, tag),
+                       [definedNames, tag]
+               );
+               const unusedCount = unusedNames.length;
+
+               const typeUsageProgress =
+                       classificationTypeDefinitions > 0
+                               ? (typesInUse / classificationTypeDefinitions) 
* 100
+                               : 0;
+               const usagePercentRounded = Math.min(
+                       100,
+                       Math.round(Number.isFinite(typeUsageProgress) ? 
typeUsageProgress : 0)
+               );
+
+               const [unusedModalOpen, setUnusedModalOpen] = useState(false);
+               const [unusedListSearchQuery, setUnusedListSearchQuery] = 
useState("");
+
+               const handleClassificationsClick = useCallback(() => {
+                       navigateToTaggedSearch(navigate);
+               }, [navigate]);
+
+               const handleOpenUnusedModal = useCallback(() => {
+                       if (unusedCount > 0 && definedNames.length > 0) {
+                               setUnusedListSearchQuery("");
+                               setUnusedModalOpen(true);
+                       }
+               }, [unusedCount, definedNames.length]);
+
+               const handleCloseUnusedModal = useCallback(() => {
+                       setUnusedListSearchQuery("");
+                       setUnusedModalOpen(false);
+               }, []);
+
+               const handleUnusedBarSegmentClick = useCallback(
+                       (e: React.MouseEvent) => {
+                               e.stopPropagation();
+                               handleOpenUnusedModal();
+                       },
+                       [handleOpenUnusedModal]
+               );
+
+               const unusedNamesFiltered = useMemo(() => {
+                       const q = unusedListSearchQuery.trim().toLowerCase();
+                       if (!q) return unusedNames;
+                       return unusedNames.filter((name) => 
name.toLowerCase().includes(q));
+               }, [unusedNames, unusedListSearchQuery]);
+
+               const showUnusedListSearch = unusedNames.length > 5;
+
+               if (isLoading) return null;
+
+               const usedBarPct = Math.min(Math.max(typeUsageProgress, 0), 
100);
+               const defsReady = definedNames.length > 0 || 
!!classificationData;
+
+               return (
+                       <Paper
+                               elevation={1}
+                               sx={{
+                                       padding: 2,
+                                       borderRadius: 2,
+                                       minHeight: 200,
+                                       height: "100%",
+                                       boxSizing: "border-box",
+                                       transition: "box-shadow 0.3s ease",
+                                       "&:hover": { boxShadow: 4 },
+                               }}
+                       >
+                               <Box sx={{ pb: 2, borderBottom: "1px solid", 
borderColor: "divider" }}>
+                                       <Typography sx={{ fontSize: "1rem", 
fontWeight: 600, color: "#1a1a1a" }}>
+                                               Classification Types In Use
+                                       </Typography>
+                               </Box>
+                               <Stack spacing={1.5} sx={{ pt: 2 }}>
+                                       <Stack
+                                               direction="row"
+                                               justifyContent="space-between"
+                                               alignItems="center"
+                                               sx={{ width: "100%" }}
+                                       >
+                                               <Typography
+                                                       sx={{
+                                                               fontSize: 
"0.875rem",
+                                                               fontWeight: 600,
+                                                               color: 
"#1a1a1a",
+                                                       }}
+                                               >
+                                                       Classifications in use
+                                               </Typography>
+                                               <Typography
+                                                       sx={{
+                                                               fontSize: 
"0.875rem",
+                                                               color: 
"#868e96",
+                                                       }}
+                                               >
+                                                       {usagePercentRounded}%
+                                               </Typography>
+                                       </Stack>
+                                       <Stack
+                                               direction="row"
+                                               sx={{
+                                                       height: 10,
+                                                       borderRadius: 5,
+                                                       overflow: "hidden",
+                                                       width: "100%",
+                                                       backgroundColor: 
"#e9ecef",
+                                               }}
+                                               aria-label="Classification 
usage: green is in use, grey is not in use"
+                                       >
+                                               {usedBarPct > 0 ? (
+                                                       <Box
+                                                               
component="button"
+                                                               type="button"
+                                                               
onClick={handleClassificationsClick}
+                                                               sx={{
+                                                                       width: 
`${usedBarPct}%`,
+                                                                       
minWidth: 0,
+                                                                       border: 
"none",
+                                                                       
padding: 0,
+                                                                       cursor: 
"pointer",
+                                                                       
backgroundColor: "#16a34a",
+                                                               }}
+                                                               
aria-label="Open classification search for types in use"
+                                                       />
+                                               ) : null}
+                                               <Box
+                                                       component="button"
+                                                       type="button"
+                                                       
onClick={handleUnusedBarSegmentClick}
+                                                       disabled={unusedCount 
=== 0 || !defsReady}
+                                                       sx={{
+                                                               flex: 1,
+                                                               minWidth: 0,
+                                                               border: "none",
+                                                               padding: 0,
+                                                               cursor:
+                                                                       
unusedCount > 0 && defsReady ? "pointer" : "default",
+                                                               
backgroundColor: "#e9ecef",
+                                                       }}
+                                                       aria-label={
+                                                               unusedCount > 0 
&& defsReady
+                                                                       ? `View 
${unusedCount} classification types not in use`
+                                                                       : "No 
unused classification types to show"
+                                                       }
+                                               />
+                                       </Stack>
+                                       {defsReady && (
+                                               <Typography
+                                                       component="p"
+                                                       sx={{
+                                                               fontSize: 
"0.875rem",
+                                                               color: 
"#6c757d",
+                                                               m: 0,
+                                                       }}
+                                               >
+                                                       <strong>Not in 
use:</strong>{" "}
+                                                       {unusedCount > 0 ? (
+                                                               <Link
+                                                                       
component="button"
+                                                                       
type="button"
+                                                                       
onClick={handleOpenUnusedModal}
+                                                                       sx={{
+                                                                               
fontSize: "0.875rem",
+                                                                               
color: "primary.main",
+                                                                               
cursor: "pointer",
+                                                                               
textDecoration: "underline",
+                                                                               
background: "none",
+                                                                               
border: "none",
+                                                                               
padding: 0,
+                                                                               
verticalAlign: "baseline",
+                                                                               
fontFamily: "inherit",
+                                                                       }}
+                                                                       
aria-label={`Show ${unusedCount} classification types not in use`}
+                                                               >
+                                                                       
{numberFormatWithComma(unusedCount)}{" "}
+                                                                       
{unusedCount === 1
+                                                                               
? "classification type"
+                                                                               
: "classification types"}
+                                                               </Link>
+                                                       ) : (
+                                                               <>
+                                                                       
{numberFormatWithComma(unusedCount)}{" "}
+                                                                       
{classificationTypeDefinitions > 0
+                                                                               
? unusedCount === 1
+                                                                               
        ? "classification type"
+                                                                               
        : "classification types"
+                                                                               
: ""}
+                                                               </>
+                                                       )}
+                                               </Typography>
+                                       )}
+                                       {!defsReady && loadingClassification ? (
+                                               <Typography variant="caption" 
sx={{ color: "#868e96" }}>
+                                                       Loading classification 
definitions…
+                                               </Typography>
+                                       ) : null}
+                                       <Typography
+                                               component="button"
+                                               type="button"
+                                               
onClick={handleClassificationsClick}
+                                               sx={{
+                                                       fontSize: "0.875rem",
+                                                       color: "#6c757d",
+                                                       background: "none",
+                                                       border: "none",
+                                                       cursor: "pointer",
+                                                       padding: 0,
+                                                       textAlign: "left",
+                                                       "&:hover": { color: 
"primary.main", textDecoration: "underline" },
+                                               }}
+                                               aria-label="Open classification 
search"
+                                       >
+                                               
{numberFormatWithComma(typesInUse)} of{" "}
+                                               
{numberFormatWithComma(classificationTypeDefinitions)}
+                                               classification types are in use 
(have at least one entity).
+                                       </Typography>
+                               </Stack>
+
+                               <CustomModal
+                                       open={unusedModalOpen}
+                                       onClose={handleCloseUnusedModal}
+                                       title="Classification types not in use"
+                                       maxWidth="sm"
+                                       button1Label="Close"
+                                       button1Handler={handleCloseUnusedModal}
+                                       button2Label=""
+                                       button2Handler={handleCloseUnusedModal}
+                                       hideButton2={true}
+                               >
+                                       <Stack spacing={2} sx={{ pt: 0.5 }}>
+                                               <Typography
+                                                       variant="body2"
+                                                       sx={{ color: "#6c757d", 
lineHeight: 1.5 }}
+                                               >
+                                                       These types are defined 
in Atlas but have no entity assignments in
+                                                       the current metrics 
snapshot.
+                                               </Typography>
+                                               {showUnusedListSearch ? (
+                                                       <TextField
+                                                               size="small"
+                                                               fullWidth
+                                                               
placeholder="Search classification name"
+                                                               
value={unusedListSearchQuery}
+                                                               onChange={(e) 
=> setUnusedListSearchQuery(e.target.value)}
+                                                               inputProps={{
+                                                                       
"aria-label": "Filter unused classifications by name",
+                                                               }}
+                                                               InputProps={{
+                                                                       
startAdornment: (
+                                                                               
<InputAdornment position="start">
+                                                                               
        <SearchIcon
+                                                                               
                sx={{ color: "#868e96", fontSize: "1.25rem" }}
+                                                                               
                aria-hidden
+                                                                               
        />
+                                                                               
</InputAdornment>
+                                                                       ),
+                                                               }}
+                                                       />
+                                               ) : null}
+                                               <Box
+                                                       sx={{
+                                                               maxHeight: 
"min(45vh, 320px)",
+                                                               overflowY: 
"auto",
+                                                       }}
+                                               >
+                                                       
{unusedNamesFiltered.length === 0 ? (
+                                                               <Typography 
variant="body2" color="text.secondary" sx={{ py: 2 }}>
+                                                                       
{unusedListSearchQuery.trim()
+                                                                               
? "No classifications match your search."
+                                                                               
: "No unused classifications to list."}
+                                                               </Typography>
+                                                       ) : (
+                                                               <List 
disablePadding>
+                                                                       
{unusedNamesFiltered.map((name) => (
+                                                                               
<ListItem
+                                                                               
        key={name}
+                                                                               
        disablePadding
+                                                                               
        sx={{
+                                                                               
                py: 1.25,
+                                                                               
                borderBottom: "1px solid",
+                                                                               
                borderColor: "divider",
+                                                                               
                "&:last-child": { borderBottom: "none" },
+                                                                               
        }}
+                                                                               
>
+                                                                               
        <Link
+                                                                               
                component={RouterLink}
+                                                                               
                to={{
+                                                                               
                        pathname: 
`/tag/tagAttribute/${encodeURIComponent(name)}`,
+                                                                               
                        search: new URLSearchParams({ tag: name }).toString(),
+                                                                               
                }}
+                                                                               
                onClick={handleCloseUnusedModal}
+                                                                               
                underline="hover"
+                                                                               
                color="primary"
+                                                                               
                sx={{
+                                                                               
                        fontSize: "0.875rem",
+                                                                               
                        fontWeight: 500,
+                                                                               
                        cursor: "pointer",
+                                                                               
                }}
+                                                                               
        >
+                                                                               
                {name}
+                                                                               
        </Link>
+                                                                               
</ListItem>
+                                                                       ))}
+                                                               </List>
+                                                       )}
+                                               </Box>
+                                       </Stack>
+                               </CustomModal>
+                       </Paper>
+               );
+       }
+);
+
+ClassificationCoverage.displayName = "ClassificationCoverage";
+
+export default ClassificationCoverage;
diff --git 
a/dashboard/src/views/DashboardOverview/ClassificationDistributionCard.tsx 
b/dashboard/src/views/DashboardOverview/ClassificationDistributionCard.tsx
new file mode 100644
index 000000000..6da4704c7
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/ClassificationDistributionCard.tsx
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { memo, useCallback, useMemo } from "react";
+import { Paper, Stack, Typography, Box, Link } from "@mui/material";
+import {
+       BarChart,
+       Bar,
+       XAxis,
+       YAxis,
+       CartesianGrid,
+       Tooltip,
+       ResponsiveContainer,
+       Cell,
+       LabelList
+} from "recharts";
+import { useNavigate } from "react-router-dom";
+import { numberFormatWithComma } from "@utils/Helper";
+import {
+       getClassificationDistribution,
+       getTagEntityAssociationTotal,
+} from "@utils/metricsUtils";
+import { navigateToSearch, navigateToClassificationSearch } from 
"@utils/dashboardSearchUtils";
+import {
+       CHART_BAR_ACTIVE_BLUE,
+       CLASSIFICATION_DISTRIBUTION_CHART_MARGIN,
+} from "./dashboardChartPalette";
+
+const BAR_COLOR = CHART_BAR_ACTIVE_BLUE;
+
+interface ClassificationDistributionCardProps {
+       tag: Record<string, unknown> | undefined;
+       isLoading?: boolean;
+}
+
+const ClassificationDistributionCard = memo(({ tag, isLoading }: 
ClassificationDistributionCardProps) => {
+       const navigate = useNavigate();
+       const data = getClassificationDistribution(tag, 5);
+       const associationTotal = useMemo(() => 
getTagEntityAssociationTotal(tag), [tag]);
+
+       const handleBarClick = useCallback(
+               (entry: { name: string }) => {
+                       navigateToClassificationSearch(navigate, entry.name);
+               },
+               [navigate]
+       );
+
+       const handleViewAll = useCallback(() => {
+               navigateToSearch(navigate, "all_classifications");
+       }, [navigate]);
+
+       const handleLabelClick = useCallback(
+               (tagName: string) => {
+                       navigateToClassificationSearch(navigate, tagName);
+               },
+               [navigate]
+       );
+
+       const renderTooltip = useCallback((props: unknown) => {
+               const p = props as { active?: boolean; payload?: Array<{ 
payload?: { name: string; count: number } }> };
+               if (!p?.active || !p?.payload?.length) return null;
+               const row = p.payload[0]?.payload;
+               if (!row) return null;
+               return (
+                       <Box sx={{ p: 1.5, bgcolor: "background.paper", 
borderRadius: 1, boxShadow: 2, minWidth: 140 }}>
+                               <Typography variant="body2" fontWeight={600} 
sx={{ mb: 0.5 }}>
+                                       {row.name}
+                               </Typography>
+                               <Typography variant="caption" display="block">
+                                       Entities: 
{numberFormatWithComma(row.count)}
+                               </Typography>
+                       </Box>
+               );
+       }, []);
+
+       if (isLoading) return null;
+
+       return (
+               <Paper
+                       elevation={1}
+                       sx={{
+                               padding: 2,
+                               borderRadius: 2,
+                               minHeight: 340,
+                               minWidth: 0,
+                               width: "100%",
+                               height: "100%",
+                               boxSizing: "border-box",
+                               transition: "box-shadow 0.3s ease",
+                               "&:hover": { boxShadow: 4 }
+                       }}
+               >
+                       <Box sx={{ pb: 2, borderBottom: "1px solid", 
borderColor: "divider" }}>
+                               <Stack direction="row" 
justifyContent="space-between" alignItems="center">
+                                       <Typography sx={{ fontSize: "1rem", 
fontWeight: 600, color: "#1a1a1a" }}>
+                                               Classification Distribution
+                                       </Typography>
+                                       <Link
+                                               component="button"
+                                               onClick={handleViewAll}
+                                               sx={{ fontSize: "0.875rem", 
cursor: "pointer", textDecoration: "none", color: "primary.main" }}
+                                               aria-label="View all 
classifications"
+                                       >
+                                               View All
+                                       </Link>
+                               </Stack>
+                       </Box>
+                       <Typography variant="body2" sx={{ color: "#6c757d", mt: 
2, lineHeight: 1.4 }}>
+                               <strong>Tag–entity associations 
(total):</strong>{" "}
+                               {numberFormatWithComma(associationTotal)}
+                       </Typography>
+                       <Typography variant="caption" sx={{ color: "#868e96", 
display: "block", mt: 0.75, lineHeight: 1.4 }}>
+                               The chart shows the top 5 classifications by 
number of entities in use.
+                       </Typography>
+                       {data.length === 0 ? (
+                               <Stack alignItems="center" 
justifyContent="center" height={200}>
+                                       <Typography variant="body2" 
color="text.secondary">
+                                               No classification data available
+                                       </Typography>
+                               </Stack>
+                       ) : (
+                               <Box sx={{ mt: 2, minHeight: 260, height: 260, 
width: "100%", minWidth: 280 }}>
+                                       <ResponsiveContainer width="100%" 
height="100%" style={{ cursor: "pointer" }}>
+                                               <BarChart
+                                                       data={data}
+                                                       layout="vertical"
+                                                       margin={{ 
...CLASSIFICATION_DISTRIBUTION_CHART_MARGIN }}
+                                               >
+                                                       <CartesianGrid 
strokeDasharray="3 3" stroke="#f0f0f0" />
+                                                       <XAxis
+                                                               type="number"
+                                                               
tickFormatter={(v) => numberFormatWithComma(v)}
+                                                               height={36}
+                                                               label={{
+                                                                       value: 
"Entity Count",
+                                                                       
position: "bottom",
+                                                                       offset: 
12,
+                                                                       style: 
{ fontSize: 11, fill: "#6c757d" },
+                                                               }}
+                                                       />
+                                                       <YAxis
+                                                               type="category"
+                                                               dataKey="name"
+                                                               width={52}
+                                                               label={{
+                                                                       value: 
"Classification",
+                                                                       angle: 
-90,
+                                                                       
position: "left",
+                                                                       offset: 
2,
+                                                                       style: 
{ fontSize: 10, fill: "#6c757d", textAnchor: "middle" },
+                                                               }}
+                                                               tick={(props: 
Record<string, unknown>) => {
+                                                                       const { 
x = 0, y = 0, payload } = props;
+                                                                       const p 
= payload as { value?: string; name?: string } | undefined;
+                                                                       const 
value = p?.value ?? p?.name ?? (typeof payload === "string" ? payload : "");
+                                                                       return (
+                                                                               
<g
+                                                                               
        transform={`translate(${x},${y})`}
+                                                                               
        onClick={() => (value ? handleLabelClick(value) : undefined)}
+                                                                               
        style={{ cursor: value ? "pointer" : "default" }}
+                                                                               
        role={value ? "button" : undefined}
+                                                                               
        tabIndex={value ? 0 : undefined}
+                                                                               
        onKeyDown={
+                                                                               
                value
+                                                                               
                        ? (e: React.KeyboardEvent<SVGGElement>) => {
+                                                                               
                                        if (e.key === "Enter" || e.key === " ") 
{
+                                                                               
                                                e.preventDefault();
+                                                                               
                                                handleLabelClick(value);
+                                                                               
                                        }
+                                                                               
                                }
+                                                                               
                        : undefined
+                                                                               
        }
+                                                                               
>
+                                                                               
        <text x={0} y={0} dy={4} textAnchor="end" fill="#333" fontSize={12}>
+                                                                               
                {value}
+                                                                               
        </text>
+                                                                               
</g>
+                                                                       );
+                                                               }}
+                                                       />
+                                                       <Tooltip 
content={renderTooltip} cursor={{ fill: "transparent" }} />
+                                                       <Bar
+                                                               dataKey="count"
+                                                               name="Entities"
+                                                               fill={BAR_COLOR}
+                                                               radius={[0, 4, 
4, 0]}
+                                                               
onClick={(entry) => handleBarClick(entry)}
+                                                               cursor="pointer"
+                                                       >
+                                                               <LabelList
+                                                                       
dataKey="count"
+                                                                       
position="right"
+                                                                       
offset={10}
+                                                                       
formatter={(v: number) => numberFormatWithComma(v)}
+                                                                       style={{
+                                                                               
fontSize: 12,
+                                                                               
fontWeight: 500,
+                                                                               
fill: BAR_COLOR,
+                                                                       }}
+                                                               />
+                                                               {data.map((_, 
index) => <Cell key={index} fill={BAR_COLOR} />)}
+                                                       </Bar>
+                                               </BarChart>
+                                       </ResponsiveContainer>
+                               </Box>
+                       )}
+               </Paper>
+       );
+});
+
+ClassificationDistributionCard.displayName = "ClassificationDistributionCard";
+
+export default ClassificationDistributionCard;
diff --git a/dashboard/src/views/DashboardOverview/DashboardOverview.tsx 
b/dashboard/src/views/DashboardOverview/DashboardOverview.tsx
new file mode 100644
index 000000000..c7bfbd551
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/DashboardOverview.tsx
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useEffect, useState, useMemo, useCallback } from "react";
+import { Grid, Stack } from "@mui/material";
+import { useAppDispatch, useAppSelector } from "@hooks/reducerHook";
+import { fetchTypeHeaderData } from 
"@redux/slice/typeDefSlices/typeDefHeaderSlice";
+import { getLatestEntities } from "@api/apiMethods/searchApiMethod";
+import type { TypeHeaderInterface } from "@models/entityTreeType";
+import DashboardSkeleton from "./DashboardSkeleton";
+import EntityTypeBarChartSkeleton from "./EntityTypeBarChartSkeleton";
+import LatestEntitiesSkeleton from "./LatestEntitiesSkeleton";
+import OverviewCard from "./OverviewCard";
+import EntityStatusDonut from "./EntityStatusDonut";
+import ClassificationCoverage from "./ClassificationCoverage";
+import EntityTypeBarChart from "./EntityTypeBarChart";
+import LatestEntitiesList from "./LatestEntitiesList";
+import RecentActivity from "./RecentActivity";
+import KafkaTopicSummaryCard from "./KafkaTopicSummaryCard";
+import ClassificationDistributionCard from "./ClassificationDistributionCard";
+
+const DashboardOverview = () => {
+       const dispatch = useAppDispatch();
+       const { metricsData, loading: metricsLoading } = useAppSelector((state: 
{ metrics: { metricsData: unknown; loading: boolean } }) => state.metrics);
+       const typeHeaderData = useAppSelector(
+               (state: { typeHeader?: { typeHeaderData?: TypeHeaderInterface[] 
| null } }) =>
+                       state.typeHeader?.typeHeaderData ?? null
+       );
+       const dashboardRefreshVersion = useAppSelector((state) => 
state.dashboardRefresh.version);
+       const [latestEntities, setLatestEntities] = useState<unknown[]>([]);
+       const [latestLoading, setLatestLoading] = useState(true);
+       const [latestError, setLatestError] = useState<string | null>(null);
+
+       const metrics = metricsData as {
+               data?: {
+                       general?: { entityCount?: number; tagCount?: number; 
stats?: Record<string, unknown> };
+                       entity?: Record<string, unknown>;
+                       tag?: Record<string, unknown>;
+               };
+       } | null;
+       const general = metrics?.data?.general;
+       const entity = metrics?.data?.entity;
+       const tag = metrics?.data?.tag;
+       const stats = general?.stats;
+       const entityCount = general?.entityCount ?? 0;
+       const tagCount = general?.tagCount ?? 0;
+
+       const isLoading = metricsLoading;
+
+       const fetchLatestEntities = useCallback(async () => {
+               setLatestLoading(true);
+               setLatestError(null);
+               try {
+                       const resp = await getLatestEntities();
+                       const entities = (resp as { data?: { entities?: 
unknown[] } })?.data?.entities ?? [];
+                       setLatestEntities(Array.isArray(entities) ? entities : 
[]);
+               } catch (err) {
+                       setLatestError(err instanceof Error ? err.message : 
"Failed to load latest entities");
+                       setLatestEntities([]);
+               } finally {
+                       setLatestLoading(false);
+               }
+       }, []);
+
+       useEffect(() => {
+               fetchLatestEntities();
+       }, [dashboardRefreshVersion, fetchLatestEntities]);
+
+       useEffect(() => {
+               dispatch(fetchTypeHeaderData());
+       }, [dispatch]);
+
+       const latestEntitiesList = useMemo(() => {
+               if (!Array.isArray(latestEntities)) return [];
+               return latestEntities.slice(0, 7) as { guid?: string; 
typeName?: string; attributes?: { name?: string; qualifiedName?: string; 
__timestamp?: number } }[];
+       }, [latestEntities]);
+
+       return (
+               <Stack
+                       spacing={3}
+                       width="100%"
+                       sx={{
+                               maxWidth: "100%",
+                               boxSizing: "border-box",
+                               backgroundColor: "#f5f7f9",
+                               padding: 3,
+                               borderRadius: 2
+                       }}
+               >
+                       <Grid container spacing={3} sx={{ width: "100%", 
alignItems: "stretch" }}>
+                               <Grid item xs={12} md={4}>
+                                       {isLoading ? <DashboardSkeleton /> : 
<OverviewCard entityCount={entityCount} tagCount={tagCount} />}
+                               </Grid>
+                               <Grid item xs={12} md={4}>
+                                       {isLoading ? <DashboardSkeleton /> : 
<EntityStatusDonut entity={entity} />}
+                               </Grid>
+                               <Grid item xs={12} md={4}>
+                                       {isLoading ? (
+                                               <DashboardSkeleton />
+                                       ) : (
+                                               <ClassificationCoverage
+                                                       
classificationTypeDefinitions={tagCount}
+                                                       tag={tag}
+                                               />
+                                       )}
+                               </Grid>
+                               <Grid item xs={12} md={8} sx={{ display: 
"flex", minWidth: 0 }}>
+                                       {isLoading ? (
+                                               <EntityTypeBarChartSkeleton />
+                                       ) : (
+                                               <EntityTypeBarChart 
entity={entity} typeHeaderData={typeHeaderData} />
+                                       )}
+                               </Grid>
+                               <Grid item xs={12} md={4} sx={{ display: 
"flex", minWidth: 0 }}>
+                                       {latestLoading ? (
+                                               <LatestEntitiesSkeleton />
+                                       ) : (
+                                               <LatestEntitiesList 
entities={latestEntitiesList} error={latestError} />
+                                       )}
+                               </Grid>
+                               <Grid item xs={12} md={12} sx={{ display: 
"flex", minWidth: 0 }}>
+                                       <RecentActivity />
+                               </Grid>
+                               <Grid item xs={12} md={12} sx={{ display: 
"flex", minWidth: 0 }}>
+                                       {isLoading ? 
<EntityTypeBarChartSkeleton /> : <ClassificationDistributionCard tag={tag} 
isLoading={isLoading} />}
+                               </Grid>
+                               <Grid item xs={12} md={12} sx={{ display: 
"flex", minWidth: 0 }}>
+                                       {isLoading ? 
<EntityTypeBarChartSkeleton /> : <KafkaTopicSummaryCard stats={stats} 
isLoading={isLoading} />}
+                               </Grid>
+                       </Grid>
+               </Stack>
+       );
+};
+
+export default DashboardOverview;
diff --git a/dashboard/src/views/DashboardOverview/DashboardSkeleton.tsx 
b/dashboard/src/views/DashboardOverview/DashboardSkeleton.tsx
new file mode 100644
index 000000000..b37ec59d4
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/DashboardSkeleton.tsx
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Paper, Stack } from "@mui/material";
+import SkeletonLoader from "@components/SkeletonLoader";
+
+const DashboardSkeleton = () => (
+       <Paper
+               elevation={1}
+               sx={{
+                       padding: 2,
+                       borderRadius: 2,
+                       minHeight: 200,
+                       transition: "box-shadow 0.3s ease",
+                       "&:hover": { boxShadow: 4 }
+               }}
+       >
+               <Stack spacing={1}>
+                       <SkeletonLoader animation="wave" variant="text" 
count={1} width="40%" height={28} />
+                       <SkeletonLoader animation="wave" variant="rectangular" 
count={1} height={60} />
+               </Stack>
+       </Paper>
+);
+
+export default DashboardSkeleton;
diff --git a/dashboard/src/views/DashboardOverview/EntityStatusDonut.tsx 
b/dashboard/src/views/DashboardOverview/EntityStatusDonut.tsx
new file mode 100644
index 000000000..9eb93dc1e
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/EntityStatusDonut.tsx
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { memo, useCallback, useState } from "react";
+import { Paper, Stack, Typography, Box } from "@mui/material";
+import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer, Sector } from 
"recharts";
+import { useNavigate } from "react-router-dom";
+import { numberFormatWithComma } from "@utils/Helper";
+import { getEntityStatusTotals } from "@utils/metricsUtils";
+import { navigateToSearch } from "@utils/dashboardSearchUtils";
+import { ENTITY_STATUS_DONUT_COLORS as COLORS } from "./dashboardChartPalette";
+
+interface EntityStatusDonutProps {
+       entity: Record<string, unknown> | undefined;
+       isLoading?: boolean;
+}
+
+const EntityStatusDonut = memo(({ entity, isLoading }: EntityStatusDonutProps) 
=> {
+       const [activeIndex, setActiveIndex] = useState<number>(-1);
+       const navigate = useNavigate();
+       const totals = getEntityStatusTotals(entity);
+       const total = totals.active + totals.shell + totals.deleted;
+
+       const chartData = [
+               { name: "Active", value: totals.active, color: COLORS.Active },
+               { name: "Shell", value: totals.shell, color: COLORS.Shell },
+               { name: "Deleted", value: totals.deleted, color: COLORS.Deleted 
}
+       ].filter((d) => d.value > 0);
+
+       const getPercent = (val: number) => (total > 0 ? Math.round((val / 
total) * 100) : 0);
+
+       const handleStatusClick = useCallback(
+               (status: "Active" | "Shell" | "Deleted") => {
+                       if (status === "Active") {
+                               navigateToSearch(navigate, "entity_status");
+                       } else if (status === "Deleted") {
+                               navigateToSearch(navigate, "entity_status", {
+                                       includeDE: true,
+                                       entityFilters: {
+                                               condition: "AND",
+                                               criterion: [{ attributeName: 
"__state", operator: "eq", attributeValue: "DELETED" }]
+                                       }
+                               });
+                       } else if (status === "Shell") {
+                               navigateToSearch(navigate, "entity_status", {
+                                       entityFilters: {
+                                               condition: "AND",
+                                               criterion: [{ attributeName: 
"__isIncomplete", operator: "eq", attributeValue: "true" }]
+                                       }
+                               });
+                       }
+               },
+               [navigate]
+       );
+
+       if (isLoading) return null;
+
+       const renderActiveShape = (props: unknown) => {
+               const p = props as { outerRadius?: number; innerRadius?: 
number; [k: string]: unknown };
+               return (
+                       <Sector
+                               {...p}
+                               outerRadius={(p.outerRadius ?? 60) * 1.08}
+                               innerRadius={p.innerRadius ?? 40}
+                       />
+               );
+       };
+
+       return (
+               <Paper
+                       elevation={1}
+                       sx={{
+                               padding: 2,
+                               borderRadius: 2,
+                               minHeight: 200,
+                               transition: "box-shadow 0.3s ease",
+                               "&:hover": { boxShadow: 4 }
+                       }}
+               >
+                       <Box sx={{ pb: 2, borderBottom: "1px solid", 
borderColor: "divider" }}>
+                               <Typography sx={{ fontSize: "1rem", fontWeight: 
600, color: "#1a1a1a" }}>
+                                       Entity Status Overview
+                               </Typography>
+                       </Box>
+                       <Stack direction="row" spacing={2} alignItems="center" 
height={160} sx={{ pt: 2 }}>
+                               <Stack spacing={1.5} flex={1}>
+                                       {(["Active", "Shell", "Deleted"] as 
const).map((status) => (
+                                               <Box
+                                                       key={status}
+                                                       component="button"
+                                                       type="button"
+                                                       onClick={() => 
handleStatusClick(status)}
+                                                       aria-label={`View 
${status} entities`}
+                                                       sx={{
+                                                               display: "flex",
+                                                               alignItems: 
"center",
+                                                               gap: 1.5,
+                                                               cursor: 
"pointer",
+                                                               background: 
"none",
+                                                               border: "none",
+                                                               padding: 0,
+                                                               margin: 0,
+                                                               font: "inherit",
+                                                               textAlign: 
"left",
+                                                               "&:hover": { 
opacity: 0.85 }
+                                                       }}
+                                               >
+                                                       <Box
+                                                               sx={{
+                                                                       width: 
12,
+                                                                       height: 
12,
+                                                                       
borderRadius: "50%",
+                                                                       
backgroundColor: COLORS[status],
+                                                                       
flexShrink: 0
+                                                               }}
+                                                       />
+                                                       <Typography 
component="span" sx={{ fontSize: "0.875rem", color: "#374151" }}>
+                                                               {status} 
{getPercent(totals[status.toLowerCase() as keyof typeof totals])}%
+                                                       </Typography>
+                                               </Box>
+                                       ))}
+                               </Stack>
+                               <ResponsiveContainer width="50%" height="100%" 
style={{ cursor: "pointer" }}>
+                                       <PieChart>
+                                               <Pie
+                                                       data={chartData}
+                                                       cx="50%"
+                                                       cy="50%"
+                                                       innerRadius={40}
+                                                       outerRadius={60}
+                                                       paddingAngle={2}
+                                                       dataKey="value"
+                                                       isAnimationActive
+                                                       animationDuration={800}
+                                                       
animationEasing="ease-out"
+                                                       
activeIndex={activeIndex}
+                                                       
activeShape={renderActiveShape}
+                                                       onMouseEnter={(_, 
index) => setActiveIndex(index)}
+                                                       onMouseLeave={() => 
setActiveIndex(-1)}
+                                                       onClick={(data) => 
handleStatusClick(data.name as "Active" | "Shell" | "Deleted")}
+                                               >
+                                                       {chartData.map((entry, 
index) => (
+                                                               <Cell 
key={`cell-${index}`} fill={entry.color} stroke="none" />
+                                                       ))}
+                                               </Pie>
+                                               <Tooltip
+                                                       formatter={(value: 
number) => numberFormatWithComma(value)}
+                                                       contentStyle={{ 
borderRadius: 8 }}
+                                               />
+                                       </PieChart>
+                               </ResponsiveContainer>
+                       </Stack>
+               </Paper>
+       );
+});
+
+EntityStatusDonut.displayName = "EntityStatusDonut";
+
+export default EntityStatusDonut;
diff --git a/dashboard/src/views/DashboardOverview/EntityTypeBarChart.tsx 
b/dashboard/src/views/DashboardOverview/EntityTypeBarChart.tsx
new file mode 100644
index 000000000..433cf228f
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/EntityTypeBarChart.tsx
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { memo, useCallback, useMemo } from "react";
+import { Paper, Stack, Typography, Link, Box } from "@mui/material";
+import {
+       BarChart,
+       Bar,
+       XAxis,
+       YAxis,
+       CartesianGrid,
+       Tooltip,
+       ResponsiveContainer,
+       Cell,
+       LabelList,
+} from "recharts";
+import { useNavigate } from "react-router-dom";
+import { numberFormatWithComma } from "@utils/Helper";
+import type { EntityTypeDistributionItem } from "@utils/metricsUtils";
+import {
+       getServiceTypeDistribution,
+       type TypeHeaderCatalogRow,
+} from "@utils/typeCatalogUtils";
+import {
+       navigateToSearch,
+       navigateToServiceTypeEntitySearch,
+} from "@utils/dashboardSearchUtils";
+import {
+       CHART_BAR_ACTIVE_BLUE,
+       ENTITY_STATUS_DONUT_COLORS,
+       HORIZONTAL_BAR_CHART_MARGIN,
+} from "./dashboardChartPalette";
+
+const ACTIVE_COLOR = CHART_BAR_ACTIVE_BLUE;
+const DELETED_COLOR = ENTITY_STATUS_DONUT_COLORS.Deleted;
+
+interface EntityTypeBarChartProps {
+       entity: Record<string, unknown> | undefined;
+       typeHeaderData?: TypeHeaderCatalogRow[] | null;
+       isLoading?: boolean;
+}
+
+const payloadFromBarEvent = (item: unknown): EntityTypeDistributionItem | 
undefined => {
+       if (!item || typeof item !== "object") return undefined;
+       const rec = item as { payload?: EntityTypeDistributionItem };
+       return rec.payload;
+};
+
+const EntityTypeBarChart = memo(
+       ({ entity, typeHeaderData, isLoading }: EntityTypeBarChartProps) => {
+               const navigate = useNavigate();
+               const data = useMemo(
+                       () => getServiceTypeDistribution(entity, 
typeHeaderData, 5),
+                       [entity, typeHeaderData]
+               );
+
+               const navigateForRow = useCallback(
+                       (row: EntityTypeDistributionItem, includeDeleted: 
boolean) => {
+                               const targets =
+                                       row.underlyingTypeNames?.length && 
row.underlyingTypeNames.length > 0
+                                               ? row.underlyingTypeNames
+                                               : [row.name];
+                               navigateToServiceTypeEntitySearch(navigate, 
targets, includeDeleted);
+                       },
+                       [navigate]
+               );
+
+               const handleActiveBarClick = useCallback(
+                       (barProps: unknown) => {
+                               const row = payloadFromBarEvent(barProps);
+                               if (row) navigateForRow(row, false);
+                       },
+                       [navigateForRow]
+               );
+
+               const handleDeletedBarClick = useCallback(
+                       (barProps: unknown) => {
+                               const row = payloadFromBarEvent(barProps);
+                               if (row) navigateForRow(row, true);
+                       },
+                       [navigateForRow]
+               );
+
+               const handleViewAll = useCallback(() => {
+                       navigateToSearch(navigate, "all_entities");
+               }, [navigate]);
+
+               const handleLabelClick = useCallback(
+                       (serviceLabel: string) => {
+                               const row = data.find((d) => d.name === 
serviceLabel);
+                               if (row) navigateForRow(row, false);
+                       },
+                       [data, navigateForRow]
+               );
+
+               const renderTooltip = useCallback((props: unknown) => {
+                       const p = props as {
+                               active?: boolean;
+                               payload?: Array<{
+                                       payload?: EntityTypeDistributionItem;
+                               }>;
+                       };
+                       if (!p?.active || !p?.payload?.length) return null;
+                       const row = p.payload[0]?.payload;
+                       if (!row) return null;
+                       return (
+                               <Box sx={{ p: 1.5, bgcolor: "background.paper", 
borderRadius: 1, boxShadow: 2, minWidth: 140 }}>
+                                       <Typography variant="body2" 
fontWeight={600} sx={{ mb: 0.5 }}>
+                                               {row.name}
+                                       </Typography>
+                                       <Typography variant="caption" 
display="block" color="primary">
+                                               Active: 
{numberFormatWithComma(row.active)}
+                                       </Typography>
+                                       <Typography variant="caption" 
display="block" sx={{ color: DELETED_COLOR }}>
+                                               Deleted: 
{numberFormatWithComma(row.deleted)}
+                                       </Typography>
+                                       <Typography variant="caption" 
display="block" fontWeight={600}>
+                                               Total: 
{numberFormatWithComma(row.count)}
+                                       </Typography>
+                               </Box>
+                       );
+               }, []);
+
+               if (isLoading) return null;
+
+               return (
+                       <Paper
+                               elevation={1}
+                               sx={{
+                                       padding: 2,
+                                       borderRadius: 2,
+                                       minHeight: 340,
+                                       minWidth: 0,
+                                       width: "100%",
+                                       height: "100%",
+                                       boxSizing: "border-box",
+                                       transition: "box-shadow 0.3s ease",
+                                       "&:hover": { boxShadow: 4 },
+                               }}
+                       >
+                               <Box sx={{ pb: 2, borderBottom: "1px solid", 
borderColor: "divider" }}>
+                                       <Stack direction="row" 
justifyContent="space-between" alignItems="center">
+                                               <Typography sx={{ fontSize: 
"1rem", fontWeight: 600, color: "#1a1a1a" }}>
+                                                       Service Type 
Distribution
+                                               </Typography>
+                                               <Link
+                                                       component="button"
+                                                       onClick={handleViewAll}
+                                                       sx={{
+                                                               fontSize: 
"0.875rem",
+                                                               cursor: 
"pointer",
+                                                               textDecoration: 
"none",
+                                                               color: 
"primary.main",
+                                                       }}
+                                                       aria-label="View all 
entities"
+                                               >
+                                                       View All
+                                               </Link>
+                                       </Stack>
+                               </Box>
+                               {data.length === 0 ? (
+                                       <Stack alignItems="center" 
justifyContent="center" height={200}>
+                                               <Typography variant="body2" 
color="text.secondary">
+                                                       No service type data 
available
+                                               </Typography>
+                                       </Stack>
+                               ) : (
+                                       <Box sx={{ mt: 2, minHeight: 260, 
height: 260, width: "100%", minWidth: 280 }}>
+                                               <Stack direction="row" 
spacing={2} sx={{ mb: 1, flexWrap: "wrap" }} aria-label="Chart legend">
+                                                       <Stack direction="row" 
alignItems="center" spacing={0.75}>
+                                                               <Box
+                                                                       sx={{
+                                                                               
width: 10,
+                                                                               
height: 10,
+                                                                               
borderRadius: "50%",
+                                                                               
backgroundColor: ACTIVE_COLOR,
+                                                                       }}
+                                                                       
aria-hidden
+                                                               />
+                                                               <Typography 
variant="caption" sx={{ color: "#6c757d", fontSize: "0.8125rem" }}>
+                                                                       Active
+                                                               </Typography>
+                                                       </Stack>
+                                                       <Stack direction="row" 
alignItems="center" spacing={0.75}>
+                                                               <Box
+                                                                       sx={{
+                                                                               
width: 10,
+                                                                               
height: 10,
+                                                                               
borderRadius: "50%",
+                                                                               
backgroundColor: DELETED_COLOR,
+                                                                       }}
+                                                                       
aria-hidden
+                                                               />
+                                                               <Typography 
variant="caption" sx={{ color: "#6c757d", fontSize: "0.8125rem" }}>
+                                                                       Deleted
+                                                               </Typography>
+                                                       </Stack>
+                                               </Stack>
+                                               <ResponsiveContainer 
width="100%" height="100%" style={{ cursor: "pointer" }}>
+                                                       <BarChart data={data} 
layout="vertical" margin={{ ...HORIZONTAL_BAR_CHART_MARGIN }}>
+                                                               <CartesianGrid 
strokeDasharray="3 3" stroke="#f0f0f0" />
+                                                               <XAxis
+                                                                       
type="number"
+                                                                       
tickFormatter={(v) => numberFormatWithComma(v)}
+                                                                       
height={36}
+                                                                       label={{
+                                                                               
value: "Entity Count",
+                                                                               
position: "bottom",
+                                                                               
offset: 12,
+                                                                               
style: { fontSize: 11, fill: "#6c757d" },
+                                                                       }}
+                                                               />
+                                                               <YAxis
+                                                                       
type="category"
+                                                                       
dataKey="name"
+                                                                       
width={88}
+                                                                       label={{
+                                                                               
value: "Service Type",
+                                                                               
angle: -90,
+                                                                               
position: "left",
+                                                                               
offset: 4,
+                                                                               
style: { fontSize: 11, fill: "#6c757d", textAnchor: "middle" },
+                                                                       }}
+                                                                       
tick={(props: Record<string, unknown>) => {
+                                                                               
const { x = 0, y = 0, payload } = props;
+                                                                               
const p = payload as { value?: string; name?: string } | undefined;
+                                                                               
const value =
+                                                                               
        p?.value ??
+                                                                               
        p?.name ??
+                                                                               
        (typeof payload === "string" ? payload : "");
+                                                                               
return (
+                                                                               
        <g
+                                                                               
                transform={`translate(${x},${y})`}
+                                                                               
                onClick={() => (value ? handleLabelClick(value) : undefined)}
+                                                                               
                style={{ cursor: value ? "pointer" : "default" }}
+                                                                               
                role={value ? "button" : undefined}
+                                                                               
                tabIndex={value ? 0 : undefined}
+                                                                               
                onKeyDown={
+                                                                               
                        value
+                                                                               
                                ? (e: React.KeyboardEvent<SVGGElement>) => {
+                                                                               
                                                if (e.key === "Enter" || e.key 
=== " ") {
+                                                                               
                                                        e.preventDefault();
+                                                                               
                                                        handleLabelClick(value);
+                                                                               
                                                }
+                                                                               
                                        }
+                                                                               
                                : undefined
+                                                                               
                }
+                                                                               
        >
+                                                                               
                <text x={0} y={0} dy={4} textAnchor="end" fill="#333" 
fontSize={12}>
+                                                                               
                        {value}
+                                                                               
                </text>
+                                                                               
        </g>
+                                                                               
);
+                                                                       }}
+                                                               />
+                                                               <Tooltip 
content={renderTooltip} cursor={{ fill: "transparent" }} />
+                                                               <Bar
+                                                                       
dataKey="active"
+                                                                       
name="Active"
+                                                                       
stackId="a"
+                                                                       
fill={ACTIVE_COLOR}
+                                                                       
radius={[0, 0, 0, 0]}
+                                                                       
isAnimationActive
+                                                                       
animationDuration={800}
+                                                                       
animationEasing="ease-out"
+                                                                       
onClick={handleActiveBarClick}
+                                                                       
cursor="pointer"
+                                                                       
activeBar={{ fill: ACTIVE_COLOR }}
+                                                               >
+                                                                       
{data.map((_, index) => (
+                                                                               
<Cell key={`active-${index}`} fill={ACTIVE_COLOR} />
+                                                                       ))}
+                                                               </Bar>
+                                                               <Bar
+                                                                       
dataKey="deleted"
+                                                                       
name="Deleted"
+                                                                       
stackId="a"
+                                                                       
fill={DELETED_COLOR}
+                                                                       
radius={[0, 4, 4, 0]}
+                                                                       
isAnimationActive
+                                                                       
animationDuration={800}
+                                                                       
animationEasing="ease-out"
+                                                                       
onClick={handleDeletedBarClick}
+                                                                       
cursor="pointer"
+                                                                       
activeBar={{ fill: DELETED_COLOR }}
+                                                               >
+                                                                       
<LabelList
+                                                                               
dataKey="count"
+                                                                               
position="right"
+                                                                               
offset={10}
+                                                                               
formatter={(v: number) => numberFormatWithComma(v)}
+                                                                               
style={{
+                                                                               
        fontSize: 12,
+                                                                               
        fontWeight: 500,
+                                                                               
        fill: ACTIVE_COLOR,
+                                                                               
}}
+                                                                       />
+                                                                       
{data.map((_, index) => (
+                                                                               
<Cell key={`deleted-${index}`} fill={DELETED_COLOR} />
+                                                                       ))}
+                                                               </Bar>
+                                                       </BarChart>
+                                               </ResponsiveContainer>
+                                       </Box>
+                               )}
+                       </Paper>
+               );
+       }
+);
+
+EntityTypeBarChart.displayName = "EntityTypeBarChart";
+
+export default EntityTypeBarChart;
diff --git 
a/dashboard/src/views/DashboardOverview/EntityTypeBarChartSkeleton.tsx 
b/dashboard/src/views/DashboardOverview/EntityTypeBarChartSkeleton.tsx
new file mode 100644
index 000000000..3f2950b0b
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/EntityTypeBarChartSkeleton.tsx
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Paper, Stack, Box } from "@mui/material";
+import SkeletonLoader from "@components/SkeletonLoader";
+
+const EntityTypeBarChartSkeleton = () => (
+       <Paper
+               elevation={1}
+               sx={{
+                       padding: 2,
+                       borderRadius: 2,
+                       minHeight: 340,
+                       minWidth: 0,
+                       width: "100%",
+                       flex: 1,
+                       boxSizing: "border-box",
+                       transition: "box-shadow 0.3s ease",
+                       "&:hover": { boxShadow: 4 }
+               }}
+       >
+               <Box sx={{ pb: 2, borderBottom: "1px solid", borderColor: 
"divider" }}>
+                       <Stack direction="row" justifyContent="space-between" 
alignItems="center">
+                               <SkeletonLoader animation="wave" variant="text" 
count={1} width="50%" height={24} />
+                               <SkeletonLoader animation="wave" variant="text" 
count={1} width={60} height={20} />
+                       </Stack>
+               </Box>
+               <Stack direction="row" spacing={2} sx={{ mt: 2, mb: 1 }}>
+                       <SkeletonLoader animation="wave" variant="text" 
count={1} width={40} height={16} />
+                       <SkeletonLoader animation="wave" variant="text" 
count={1} width={50} height={16} />
+               </Stack>
+               <Stack spacing={1.5} sx={{ mt: 2 }}>
+                       {[1, 2, 3, 4, 5].map((i) => (
+                               <Stack key={i} direction="row" 
alignItems="center" spacing={2}>
+                                       <SkeletonLoader animation="wave" 
variant="text" count={1} width={100} height={20} />
+                                       <SkeletonLoader animation="wave" 
variant="rectangular" count={1} width={`${30 + i * 12}%`} height={24} sx={{ 
borderRadius: 1 }} />
+                               </Stack>
+                       ))}
+               </Stack>
+       </Paper>
+);
+
+export default EntityTypeBarChartSkeleton;
diff --git a/dashboard/src/views/DashboardOverview/KafkaTopicSummaryCard.tsx 
b/dashboard/src/views/DashboardOverview/KafkaTopicSummaryCard.tsx
new file mode 100644
index 000000000..93c00f50b
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/KafkaTopicSummaryCard.tsx
@@ -0,0 +1,402 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Fragment, memo, useMemo, useState, useCallback } from "react";
+import {
+       Paper,
+       Stack,
+       Typography,
+       Table,
+       TableBody,
+       TableCell,
+       TableContainer,
+       TableHead,
+       TableRow,
+       Box,
+       IconButton,
+       Tooltip,
+       Collapse,
+} from "@mui/material";
+import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
+import ExpandLessIcon from "@mui/icons-material/ExpandLess";
+import { numberFormatWithComma } from "@utils/Helper";
+import { formatedDate } from "@utils/Utils";
+import {
+       parseMetricsStats,
+       getMessageConsumptionData,
+       getMessageConsumptionDataExcludingTotal,
+       buildTopicNotificationRecord,
+       topicRowHasPeriodMetrics,
+       type MessageConsumptionItem,
+} from "@utils/metricsUtils";
+import MessageConsumptionChart from "./MessageConsumptionChart";
+import {
+       CHART_BAR_ACTIVE_BLUE,
+       ENTITY_STATUS_DONUT_COLORS,
+} from "./dashboardChartPalette";
+
+const CREATES_COLOR = ENTITY_STATUS_DONUT_COLORS.Active;
+const UPDATES_COLOR = CHART_BAR_ACTIVE_BLUE;
+const DELETES_COLOR = ENTITY_STATUS_DONUT_COLORS.Deleted;
+
+interface TopicDetail {
+       topic: string;
+       processed: number;
+       failed: number;
+       lastProcessed: string | number;
+       /** Partition stats — same shape as aggregate Notification (per 
AtlasMetricsUtil). */
+       topicStats: Record<string, unknown>;
+}
+
+interface KafkaTopicSummaryCardProps {
+       stats: Record<string, unknown> | undefined;
+       isLoading?: boolean;
+}
+
+const getTopicConsumptionPanelId = (topic: string): string =>
+       `kafka-topic-msg-panel-${topic.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
+
+const TotalProcessedTooltip = ({
+       total,
+}: {
+       total: MessageConsumptionItem | undefined;
+}) => {
+       if (!total) {
+               return (
+                       <Typography variant="caption" component="span">
+                               No breakdown available
+                       </Typography>
+               );
+       }
+       return (
+               <Box sx={{ p: 1, minWidth: 160, bgcolor: "#fff" }}>
+                       <Typography
+                               variant="body2"
+                               fontWeight={600}
+                               sx={{ mb: 0.5, color: "#1a1a1a" }}
+                       >
+                               {total.period}
+                       </Typography>
+                       <Typography variant="caption" display="block" sx={{ 
color: CREATES_COLOR }}>
+                               Creates: {numberFormatWithComma(total.creates)}
+                       </Typography>
+                       <Typography variant="caption" display="block" sx={{ 
color: UPDATES_COLOR }}>
+                               Updates: {numberFormatWithComma(total.updates)}
+                       </Typography>
+                       <Typography variant="caption" display="block" sx={{ 
color: DELETES_COLOR }}>
+                               Deletes: {numberFormatWithComma(total.deletes)}
+                       </Typography>
+                       <Typography variant="caption" display="block" sx={{ 
color: "#6c757d", mt: 0.5 }}>
+                               Messages processed: 
{numberFormatWithComma(total.count)}
+                       </Typography>
+                       <Typography variant="caption" display="block" sx={{ 
color: "#6c757d" }}>
+                               Avg time (ms): 
{numberFormatWithComma(total.avgTime)}
+                       </Typography>
+               </Box>
+       );
+};
+
+const KafkaTopicSummaryCard = memo(({ stats, isLoading }: 
KafkaTopicSummaryCardProps) => {
+       const [sortKey, setSortKey] = useState<"topic" | "processed" | 
"failed">("topic");
+       const [sortOrder, setSortOrder] = useState<"asc" | "desc">("asc");
+       /** One expanded topic at a time to limit vertical growth. */
+       const [expandedTopic, setExpandedTopic] = useState<string | null>(null);
+
+       const parsed = useMemo(() => parseMetricsStats(stats), [stats]);
+       const notification = parsed?.Notification as Record<string, unknown> | 
undefined;
+       const topicDetails = notification?.topicDetails as
+               | Record<string, Record<string, unknown>>
+               | undefined;
+
+       const rows = useMemo((): TopicDetail[] => {
+               if (!topicDetails || typeof topicDetails !== "object") return 
[];
+               return Object.entries(topicDetails).map(([topic, data]) => {
+                       const lp = data?.lastMessageProcessedTime;
+                       const lastProcessed: string | number =
+                               lp != null && typeof lp !== "object" ? (lp as 
string | number) : "-";
+                       return {
+                               topic,
+                               processed: Number(data?.processedMessageCount 
?? 0),
+                               failed: Number(data?.failedMessageCount ?? 0),
+                               lastProcessed,
+                               topicStats: data ?? {},
+                       };
+               });
+       }, [topicDetails]);
+
+       const sortedRows = useMemo(() => {
+               const list = [...rows];
+               const dir = sortOrder === "asc" ? 1 : -1;
+               return list.sort((a, b) => {
+                       if (sortKey === "topic") {
+                               const av = String(a.topic).toLowerCase();
+                               const bv = String(b.topic).toLowerCase();
+                               return (av < bv ? -1 : av > bv ? 1 : 0) * dir;
+                       }
+                       const av = a[sortKey];
+                       const bv = b[sortKey];
+                       return ((av as number) - (bv as number)) * dir;
+               });
+       }, [rows, sortKey, sortOrder]);
+
+       const consumptionByTopic = useMemo(() => {
+               const m = new Map<
+                       string,
+                       { totalRow: MessageConsumptionItem | undefined; 
chartData: MessageConsumptionItem[] }
+               >();
+               for (const row of rows) {
+                       const record = 
buildTopicNotificationRecord(row.topicStats, {
+                               aggregateNotification: notification,
+                               useAggregateFallback: 
!topicRowHasPeriodMetrics(row.topicStats),
+                       });
+                       const full = getMessageConsumptionData(record);
+                       m.set(row.topic, {
+                               totalRow: full.find((d) => d.period === 
"Total"),
+                               chartData: 
getMessageConsumptionDataExcludingTotal(record),
+                       });
+               }
+               return m;
+       }, [rows, notification]);
+
+       const handleSort = useCallback((key: "topic" | "processed" | "failed") 
=> {
+               setSortKey(key);
+               setSortOrder((prev) => (prev === "asc" ? "desc" : "asc"));
+       }, []);
+
+       const handleToggleExpand = useCallback((topic: string) => {
+               setExpandedTopic((prev) => (prev === topic ? null : topic));
+       }, []);
+
+       const formatLastProcessed = (val: string | number): string => {
+               if (val === "-" || val == null) return "-";
+               if (typeof val === "number") return formatedDate({ date: val });
+               return String(val);
+       };
+
+       const hasExpanded = expandedTopic !== null;
+
+       if (isLoading) return null;
+
+       return (
+               <Paper
+                       elevation={1}
+                       sx={{
+                               padding: 2,
+                               borderRadius: 2,
+                               minHeight: 280,
+                               width: "100%",
+                               boxSizing: "border-box",
+                               transition: "box-shadow 0.3s ease",
+                               "&:hover": { boxShadow: 4 },
+                       }}
+               >
+                       <Box sx={{ pb: 2, borderBottom: "1px solid", 
borderColor: "divider" }}>
+                               <Typography sx={{ fontSize: "1rem", fontWeight: 
600, color: "#1a1a1a" }}>
+                                       Kafka Topic Summary
+                               </Typography>
+                       </Box>
+                       {rows.length === 0 ? (
+                               <Stack alignItems="center" 
justifyContent="center" height={180}>
+                                       <Typography variant="body2" 
color="text.secondary">
+                                               No topic data available
+                                       </Typography>
+                               </Stack>
+                       ) : (
+                               <TableContainer sx={{ maxHeight: hasExpanded ? 
560 : 220, mt: 1 }}>
+                                       <Table size="small" stickyHeader>
+                                               <TableHead>
+                                                       <TableRow>
+                                                               <TableCell
+                                                                       
onClick={() => handleSort("topic")}
+                                                                       sx={{ 
cursor: "pointer", fontWeight: 600 }}
+                                                                       
aria-label="Sort by topic"
+                                                               >
+                                                                       Topic{" 
"}
+                                                                       
{sortKey === "topic"
+                                                                               
? sortOrder === "asc"
+                                                                               
        ? "▲"
+                                                                               
        : "▼"
+                                                                               
: ""}
+                                                               </TableCell>
+                                                               <TableCell
+                                                                       
align="right"
+                                                                       
onClick={() => handleSort("processed")}
+                                                                       sx={{ 
cursor: "pointer", fontWeight: 600 }}
+                                                                       
aria-label="Sort by processed"
+                                                               >
+                                                                       
Processed{" "}
+                                                                       
{sortKey === "processed"
+                                                                               
? sortOrder === "asc"
+                                                                               
        ? "▲"
+                                                                               
        : "▼"
+                                                                               
: ""}
+                                                               </TableCell>
+                                                               <TableCell
+                                                                       
align="right"
+                                                                       
onClick={() => handleSort("failed")}
+                                                                       sx={{ 
cursor: "pointer", fontWeight: 600 }}
+                                                                       
aria-label="Sort by failed"
+                                                               >
+                                                                       
Failed{" "}
+                                                                       
{sortKey === "failed"
+                                                                               
? sortOrder === "asc"
+                                                                               
        ? "▲"
+                                                                               
        : "▼"
+                                                                               
: ""}
+                                                               </TableCell>
+                                                               <TableCell 
align="right" sx={{ fontWeight: 600 }}>
+                                                                       Last 
Processed
+                                                               </TableCell>
+                                                       </TableRow>
+                                               </TableHead>
+                                               <TableBody>
+                                                       {sortedRows.map((row) 
=> {
+                                                               const 
isExpanded = expandedTopic === row.topic;
+                                                               const panelId = 
getTopicConsumptionPanelId(row.topic);
+                                                               const cons = 
consumptionByTopic.get(row.topic);
+                                                               const 
totalForHover = cons?.totalRow;
+                                                               const chartData 
= cons?.chartData ?? [];
+                                                               return (
+                                                                       
<Fragment key={row.topic}>
+                                                                               
<TableRow hover>
+                                                                               
        <TableCell sx={{ fontSize: "0.8125rem" }}>
+                                                                               
                <Stack direction="row" alignItems="center" spacing={0.5}>
+                                                                               
                        <IconButton
+                                                                               
                                size="small"
+                                                                               
                                aria-label={
+                                                                               
                                        isExpanded
+                                                                               
                                                ? `Collapse message consumption 
for ${row.topic}`
+                                                                               
                                                : `Expand message consumption 
for ${row.topic}`
+                                                                               
                                }
+                                                                               
                                aria-expanded={isExpanded}
+                                                                               
                                aria-controls={panelId}
+                                                                               
                                id={`${panelId}-trigger`}
+                                                                               
                                onClick={(e) => {
+                                                                               
                                        e.stopPropagation();
+                                                                               
                                        handleToggleExpand(row.topic);
+                                                                               
                                }}
+                                                                               
                                onKeyDown={(e) => {
+                                                                               
                                        if (e.key === " " || e.key === "Enter") 
{
+                                                                               
                                                e.stopPropagation();
+                                                                               
                                        }
+                                                                               
                                }}
+                                                                               
                        >
+                                                                               
                                {isExpanded ? (
+                                                                               
                                        <ExpandLessIcon fontSize="small" />
+                                                                               
                                ) : (
+                                                                               
                                        <ExpandMoreIcon fontSize="small" />
+                                                                               
                                )}
+                                                                               
                        </IconButton>
+                                                                               
                        <Typography
+                                                                               
                                component="span"
+                                                                               
                                variant="body2"
+                                                                               
                                sx={{ fontSize: "0.8125rem" }}
+                                                                               
                        >
+                                                                               
                                {row.topic}
+                                                                               
                        </Typography>
+                                                                               
                </Stack>
+                                                                               
        </TableCell>
+                                                                               
        <TableCell align="right" sx={{ fontSize: "0.8125rem" }}>
+                                                                               
                <Tooltip
+                                                                               
                        title={<TotalProcessedTooltip total={totalForHover} />}
+                                                                               
                        arrow
+                                                                               
                        enterDelay={200}
+                                                                               
                        placement="top"
+                                                                               
                        componentsProps={{
+                                                                               
                                tooltip: {
+                                                                               
                                        sx: {
+                                                                               
                                                bgcolor: "#fff",
+                                                                               
                                                color: "#1a1a1a",
+                                                                               
                                                border: "1px solid",
+                                                                               
                                                borderColor: "rgba(0, 0, 0, 
0.12)",
+                                                                               
                                                boxShadow: 2,
+                                                                               
                                        },
+                                                                               
                                },
+                                                                               
                                arrow: {
+                                                                               
                                        sx: {
+                                                                               
                                                color: "#fff",
+                                                                               
                                        },
+                                                                               
                                },
+                                                                               
                        }}
+                                                                               
                >
+                                                                               
                        <Box
+                                                                               
                                component="span"
+                                                                               
                                tabIndex={0}
+                                                                               
                                sx={{
+                                                                               
                                        cursor: "help",
+                                                                               
                                        borderBottom: "1px dotted",
+                                                                               
                                        borderColor: "text.secondary",
+                                                                               
                                }}
+                                                                               
                                aria-label="Total processed — hover for 
creates, updates, deletes"
+                                                                               
                        >
+                                                                               
                                {numberFormatWithComma(row.processed)}
+                                                                               
                        </Box>
+                                                                               
                </Tooltip>
+                                                                               
        </TableCell>
+                                                                               
        <TableCell align="right" sx={{ fontSize: "0.8125rem" }}>
+                                                                               
                {numberFormatWithComma(row.failed)}
+                                                                               
        </TableCell>
+                                                                               
        <TableCell align="right" sx={{ fontSize: "0.8125rem" }}>
+                                                                               
                {formatLastProcessed(row.lastProcessed)}
+                                                                               
        </TableCell>
+                                                                               
</TableRow>
+                                                                               
{isExpanded ? (
+                                                                               
        <TableRow>
+                                                                               
                <TableCell
+                                                                               
                        colSpan={4}
+                                                                               
                        sx={{ p: 0, borderBottom: "none" }}
+                                                                               
                >
+                                                                               
                        <Collapse in={isExpanded} timeout="auto" unmountOnExit>
+                                                                               
                                <Box
+                                                                               
                                        id={panelId}
+                                                                               
                                        sx={{
+                                                                               
                                                py: 2,
+                                                                               
                                                px: 2,
+                                                                               
                                                bgcolor: "action.hover",
+                                                                               
                                                borderBottom: "1px solid",
+                                                                               
                                                borderColor: "divider",
+                                                                               
                                        }}
+                                                                               
                                >
+                                                                               
                                        <Typography
+                                                                               
                                                variant="subtitle2"
+                                                                               
                                                sx={{ mb: 1, fontWeight: 600, 
color: "#1a1a1a" }}
+                                                                               
                                        >
+                                                                               
                                                Message consumption
+                                                                               
                                        </Typography>
+                                                                               
                                        <MessageConsumptionChart
+                                                                               
                                                data={chartData}
+                                                                               
                                                chartAriaLabel={`Message 
consumption for ${row.topic}`}
+                                                                               
                                        />
+                                                                               
                                </Box>
+                                                                               
                        </Collapse>
+                                                                               
                </TableCell>
+                                                                               
        </TableRow>
+                                                                               
) : null}
+                                                                       
</Fragment>
+                                                               );
+                                                       })}
+                                               </TableBody>
+                                       </Table>
+                               </TableContainer>
+                       )}
+               </Paper>
+       );
+});
+
+KafkaTopicSummaryCard.displayName = "KafkaTopicSummaryCard";
+
+export default KafkaTopicSummaryCard;
diff --git a/dashboard/src/views/DashboardOverview/MessageConsumptionChart.tsx 
b/dashboard/src/views/DashboardOverview/MessageConsumptionChart.tsx
new file mode 100644
index 000000000..f2b98f687
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/MessageConsumptionChart.tsx
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { memo, useCallback } from "react";
+import { Stack, Typography, Box } from "@mui/material";
+import {
+       BarChart,
+       Bar,
+       XAxis,
+       YAxis,
+       CartesianGrid,
+       Tooltip,
+       ResponsiveContainer,
+       Cell,
+       LabelList,
+} from "recharts";
+import { numberFormatWithComma } from "@utils/Helper";
+import { type MessageConsumptionItem } from "@utils/metricsUtils";
+import {
+       CHART_BAR_ACTIVE_BLUE,
+       ENTITY_STATUS_DONUT_COLORS,
+} from "./dashboardChartPalette";
+
+const CREATES_COLOR = ENTITY_STATUS_DONUT_COLORS.Active;
+const UPDATES_COLOR = CHART_BAR_ACTIVE_BLUE;
+const DELETES_COLOR = ENTITY_STATUS_DONUT_COLORS.Deleted;
+
+interface MessageConsumptionChartProps {
+       /** Rows must already exclude the Total period when used from Kafka 
Topic Summary. */
+       data: MessageConsumptionItem[];
+       /** Optional accessible name for the chart region (embedded context). */
+       chartAriaLabel?: string;
+}
+
+const MessageConsumptionChart = memo(
+       ({ data, chartAriaLabel }: MessageConsumptionChartProps) => {
+               const renderTooltip = useCallback(
+                       (props: unknown) => {
+                               const p = props as {
+                                       active?: boolean;
+                                       label?: string | number;
+                                       payload?: Array<{ payload?: 
MessageConsumptionItem }>;
+                               };
+                               if (!p?.active) return null;
+                               const periodLabel =
+                                       p.label !== undefined && p.label !== 
null ? String(p.label) : "";
+                               const rowFromLabel = periodLabel
+                                       ? data.find((d) => d.period === 
periodLabel)
+                                       : undefined;
+                               const row =
+                                       rowFromLabel ?? p.payload?.[0]?.payload 
?? undefined;
+                               if (!row) return null;
+                               return (
+                                       <Box
+                                               sx={{
+                                                       p: 1.5,
+                                                       bgcolor: 
"background.paper",
+                                                       borderRadius: 1,
+                                                       boxShadow: 2,
+                                                       minWidth: 160,
+                                               }}
+                                       >
+                                               <Typography variant="body2" 
fontWeight={600} sx={{ mb: 0.5 }}>
+                                                       {row.period}
+                                               </Typography>
+                                               <Typography variant="caption" 
display="block" sx={{ color: CREATES_COLOR }}>
+                                                       Creates: 
{numberFormatWithComma(row.creates)}
+                                               </Typography>
+                                               <Typography variant="caption" 
display="block" sx={{ color: UPDATES_COLOR }}>
+                                                       Updates: 
{numberFormatWithComma(row.updates)}
+                                               </Typography>
+                                               <Typography variant="caption" 
display="block" sx={{ color: DELETES_COLOR }}>
+                                                       Deletes: 
{numberFormatWithComma(row.deletes)}
+                                               </Typography>
+                                               <Typography variant="caption" 
display="block" sx={{ color: "#6c757d", mt: 0.5 }}>
+                                                       Messages processed: 
{numberFormatWithComma(row.count)}
+                                               </Typography>
+                                               <Typography variant="caption" 
display="block" sx={{ color: "#6c757d" }}>
+                                                       Avg time (ms): 
{numberFormatWithComma(row.avgTime)}
+                                               </Typography>
+                                       </Box>
+                               );
+                       },
+                       [data]
+               );
+
+               if (data.length === 0) {
+                       return (
+                               <Stack alignItems="center" 
justifyContent="center" minHeight={200}>
+                                       <Typography variant="body2" 
color="text.secondary">
+                                               No message consumption data 
available
+                                       </Typography>
+                               </Stack>
+                       );
+               }
+
+               return (
+                       <Box
+                               role={chartAriaLabel ? "region" : undefined}
+                               aria-label={chartAriaLabel}
+                               sx={{ minHeight: 260, height: 260, width: 
"100%", minWidth: 280 }}
+                       >
+                               <Stack
+                                       direction="row"
+                                       spacing={2}
+                                       sx={{ mb: 1, flexWrap: "wrap" }}
+                                       aria-label="Chart legend"
+                               >
+                                       <Stack direction="row" 
alignItems="center" spacing={0.75}>
+                                               <Box
+                                                       sx={{
+                                                               width: 10,
+                                                               height: 10,
+                                                               borderRadius: 
"50%",
+                                                               
backgroundColor: CREATES_COLOR,
+                                                       }}
+                                                       aria-hidden
+                                               />
+                                               <Typography
+                                                       variant="caption"
+                                                       sx={{ color: "#6c757d", 
fontSize: "0.8125rem" }}
+                                               >
+                                                       Creates
+                                               </Typography>
+                                       </Stack>
+                                       <Stack direction="row" 
alignItems="center" spacing={0.75}>
+                                               <Box
+                                                       sx={{
+                                                               width: 10,
+                                                               height: 10,
+                                                               borderRadius: 
"50%",
+                                                               
backgroundColor: UPDATES_COLOR,
+                                                       }}
+                                                       aria-hidden
+                                               />
+                                               <Typography
+                                                       variant="caption"
+                                                       sx={{ color: "#6c757d", 
fontSize: "0.8125rem" }}
+                                               >
+                                                       Updates
+                                               </Typography>
+                                       </Stack>
+                                       <Stack direction="row" 
alignItems="center" spacing={0.75}>
+                                               <Box
+                                                       sx={{
+                                                               width: 10,
+                                                               height: 10,
+                                                               borderRadius: 
"50%",
+                                                               
backgroundColor: DELETES_COLOR,
+                                                       }}
+                                                       aria-hidden
+                                               />
+                                               <Typography
+                                                       variant="caption"
+                                                       sx={{ color: "#6c757d", 
fontSize: "0.8125rem" }}
+                                               >
+                                                       Deletes
+                                               </Typography>
+                                       </Stack>
+                               </Stack>
+                               <ResponsiveContainer width="100%" height="100%">
+                                       <BarChart
+                                               data={data}
+                                               margin={{ top: 36, right: 28, 
left: 52, bottom: 36 }}
+                                       >
+                                               <CartesianGrid 
strokeDasharray="3 3" stroke="#f0f0f0" />
+                                               <XAxis
+                                                       dataKey="period"
+                                                       tick={{ fontSize: 11 }}
+                                                       height={36}
+                                                       label={{
+                                                               value: "Period",
+                                                               position: 
"bottom",
+                                                               offset: 12,
+                                                               style: { 
fontSize: 11, fill: "#6c757d" },
+                                                       }}
+                                               />
+                                               <YAxis
+                                                       tickFormatter={(v) => 
numberFormatWithComma(v)}
+                                                       width={48}
+                                                       label={{
+                                                               value: "Count",
+                                                               angle: -90,
+                                                               position: 
"left",
+                                                               offset: 6,
+                                                               style: { 
fontSize: 11, fill: "#6c757d", textAnchor: "middle" },
+                                                       }}
+                                               />
+                                               <Tooltip 
content={renderTooltip} cursor={{ fill: "transparent" }} />
+                                               <Bar
+                                                       dataKey="creates"
+                                                       name="Creates"
+                                                       stackId="a"
+                                                       fill={CREATES_COLOR}
+                                                       radius={[0, 0, 0, 0]}
+                                               >
+                                                       {data.map((_, index) => 
(
+                                                               <Cell 
key={`creates-${index}`} fill={CREATES_COLOR} />
+                                                       ))}
+                                               </Bar>
+                                               <Bar
+                                                       dataKey="updates"
+                                                       name="Updates"
+                                                       stackId="a"
+                                                       fill={UPDATES_COLOR}
+                                                       radius={[0, 0, 0, 0]}
+                                               >
+                                                       {data.map((_, index) => 
(
+                                                               <Cell 
key={`updates-${index}`} fill={UPDATES_COLOR} />
+                                                       ))}
+                                               </Bar>
+                                               <Bar
+                                                       dataKey="deletes"
+                                                       name="Deletes"
+                                                       stackId="a"
+                                                       fill={DELETES_COLOR}
+                                                       radius={[0, 4, 4, 0]}
+                                               >
+                                                       <LabelList
+                                                               dataKey="count"
+                                                               position="top"
+                                                               offset={8}
+                                                               formatter={(v: 
number) => numberFormatWithComma(v)}
+                                                               style={{
+                                                                       
fontSize: 11,
+                                                                       
fontWeight: 600,
+                                                                       fill: 
"#374151",
+                                                               }}
+                                                       />
+                                                       {data.map((_, index) => 
(
+                                                               <Cell 
key={`deletes-${index}`} fill={DELETES_COLOR} />
+                                                       ))}
+                                               </Bar>
+                                       </BarChart>
+                               </ResponsiveContainer>
+                       </Box>
+               );
+       }
+);
+
+MessageConsumptionChart.displayName = "MessageConsumptionChart";
+
+export default MessageConsumptionChart;
diff --git a/dashboard/src/views/DashboardOverview/OverviewCard.tsx 
b/dashboard/src/views/DashboardOverview/OverviewCard.tsx
new file mode 100644
index 000000000..41018055b
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/OverviewCard.tsx
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Paper, Stack, Typography, Box } from "@mui/material";
+import { numberFormatWithComma } from "@utils/Helper";
+import { useNavigate } from "react-router-dom";
+import { navigateToSearch } from "@utils/dashboardSearchUtils";
+
+interface OverviewCardProps {
+       entityCount: number;
+       tagCount: number;
+       isLoading?: boolean;
+}
+
+const OverviewCard = ({ entityCount, tagCount, isLoading }: OverviewCardProps) 
=> {
+       const navigate = useNavigate();
+
+       const handleEntitiesClick = () => {
+               navigateToSearch(navigate, "all_entities");
+       };
+
+       const handleClassificationsClick = () => {
+               navigateToSearch(navigate, "all_classifications");
+       };
+
+       if (isLoading) return null;
+
+       return (
+               <Paper
+                       elevation={1}
+                       sx={{
+                               padding: 2,
+                               borderRadius: 2,
+                               minHeight: 200,
+                               height: "100%",
+                               boxSizing: "border-box",
+                               transition: "box-shadow 0.3s ease",
+                               "&:hover": { boxShadow: 4 }
+                       }}
+               >
+                       <Box sx={{ pb: 2, borderBottom: "1px solid", 
borderColor: "divider" }}>
+                               <Typography sx={{ fontSize: "1rem", fontWeight: 
600, color: "#1a1a1a" }}>
+                                       Overview
+                               </Typography>
+                       </Box>
+                       <Stack direction="column" spacing={3} sx={{ pt: 2 }}>
+                               <Stack alignItems="flex-start" spacing={0.5}>
+                                       <Typography
+                                               component="button"
+                                               sx={{
+                                                       fontSize: "1.75rem",
+                                                       fontWeight: 700,
+                                                       background: "none",
+                                                       border: "none",
+                                                       cursor: "pointer",
+                                                       padding: 0,
+                                                       color: "#1a1a1a",
+                                                       textAlign: "left",
+                                                       lineHeight: 1.2,
+                                                       "&:hover": { 
textDecoration: "underline", color: "primary.main" }
+                                               }}
+                                               onClick={handleEntitiesClick}
+                                               aria-label="View all entities"
+                                       >
+                                               
{numberFormatWithComma(entityCount)}
+                                       </Typography>
+                                       <Typography sx={{ fontSize: "0.875rem", 
color: "#6c757d", textTransform: "capitalize" }}>
+                                               Entities
+                                       </Typography>
+                               </Stack>
+                               <Stack alignItems="flex-start" spacing={0.5}>
+                                       <Typography
+                                               component="button"
+                                               sx={{
+                                                       fontSize: "1.75rem",
+                                                       fontWeight: 700,
+                                                       background: "none",
+                                                       border: "none",
+                                                       cursor: "pointer",
+                                                       padding: 0,
+                                                       color: "#1a1a1a",
+                                                       textAlign: "left",
+                                                       lineHeight: 1.2,
+                                                       "&:hover": { 
textDecoration: "underline", color: "primary.main" }
+                                               }}
+                                               
onClick={handleClassificationsClick}
+                                               aria-label="View all 
classifications"
+                                       >
+                                               
{numberFormatWithComma(tagCount)}
+                                       </Typography>
+                                       <Typography sx={{ fontSize: "0.875rem", 
color: "#6c757d", textTransform: "capitalize" }}>
+                                               Classifications
+                                       </Typography>
+                               </Stack>
+                       </Stack>
+               </Paper>
+       );
+};
+
+export default OverviewCard;
diff --git a/dashboard/src/views/DashboardOverview/RecentActivity.tsx 
b/dashboard/src/views/DashboardOverview/RecentActivity.tsx
new file mode 100644
index 000000000..fdd5be150
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/RecentActivity.tsx
@@ -0,0 +1,408 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { memo, useCallback, useEffect, useState } from "react";
+import { useAppSelector } from "@hooks/reducerHook";
+import { Paper, Stack, Typography, Link, Box, Chip, List, ListItem } from 
"@mui/material";
+import { RecentActivityListSkeleton } from "./RecentActivitySkeleton";
+import TypeDefAuditDetailModal from "@components/TypeDefAuditDetailModal";
+import { Link as RouterLink, useNavigate } from "react-router-dom";
+import { getAuditData } from "@api/apiMethods/detailpageApiMethod";
+import { category } from "@utils/Enum";
+import { extractTypeDefDetailObject } from "@utils/auditTypeDefUtils";
+import { dateFormat, isEmpty, jsonParse } from "@utils/Utils";
+
+export interface AuditRecord {
+       guid?: string;
+       userName?: string;
+       operation?: string;
+       params?: string;
+       result?: string;
+       startTime?: number;
+       endTime?: number;
+}
+
+const AUDIT_TABS = [
+       { id: "typeCreated", label: "Created", operations: ["TYPE_DEF_CREATE"] 
},
+       { id: "typeUpdated", label: "Updated", operations: ["TYPE_DEF_UPDATE"] 
},
+       { id: "typeDeleted", label: "Deleted", operations: ["TYPE_DEF_DELETE"] 
},
+       { id: "purge", label: "Purge", operations: ["PURGE", "AUTO_PURGE"] },
+       { id: "import", label: "Import", operations: ["IMPORT"] },
+       { id: "export", label: "Export", operations: ["EXPORT"] }
+] as const;
+
+interface ParsedAuditResult {
+       typeLabel: string;
+       entityName: string;
+       entityGuid?: string;
+       actionPhrase: string;
+       user: string;
+       dateStr: string;
+}
+
+const parseAuditRecord = (record: AuditRecord): ParsedAuditResult => {
+       const { operation, params, result, userName, endTime } = record;
+       const user = userName || "Unknown";
+       const dateStr = endTime ? dateFormat(endTime) : "";
+       let typeLabel = category[params as keyof typeof category] || params || 
"Type";
+       let actionPhrase = "";
+       let entityName = "";
+       let entityGuid = "";
+
+       if (operation === "PURGE" || operation === "AUTO_PURGE") {
+               try {
+                       const guidStr = typeof result === "string" ? 
result.replace("[", "").replace("]", "").split(",")[0]?.trim() : "";
+                       entityGuid = guidStr ?? "";
+                       if (entityGuid) entityName = "View entity";
+               } catch {
+                       /* ignore */
+               }
+               actionPhrase = "operation was performed";
+               return { typeLabel: operation === "AUTO_PURGE" ? "Auto purge" : 
"Purge", entityName, entityGuid, actionPhrase, user, dateStr };
+       }
+       if (operation === "EXPORT") {
+               return { typeLabel: "Export", entityName: "", entityGuid: "", 
actionPhrase: "operation was performed", user, dateStr };
+       }
+       if (operation === "IMPORT") {
+               return { typeLabel: "Import", entityName: "", entityGuid: "", 
actionPhrase: "operation was performed", user, dateStr };
+       }
+
+       if (operation === "TYPE_DEF_CREATE") {
+               actionPhrase = "was created";
+       } else if (operation === "TYPE_DEF_UPDATE") {
+               actionPhrase = "was updated";
+       } else if (operation === "TYPE_DEF_DELETE") {
+               actionPhrase = "was deleted";
+       } else {
+               return { typeLabel: operation || "", entityName: "", 
entityGuid: "", actionPhrase: "", user, dateStr };
+       }
+
+       try {
+               const resultObj = typeof result === "string" ? 
jsonParse(result) : result;
+               if (resultObj?.name) {
+                       entityName = resultObj.name;
+                       entityGuid = resultObj.guid ?? "";
+               } else if (resultObj && typeof resultObj === "object") {
+                       const paramsKey = params?.split(",")[0]?.trim();
+                       const arr = paramsKey ? resultObj[paramsKey] : 
resultObj[Object.keys(resultObj)[0]];
+                       if (Array.isArray(arr) && arr[0]) {
+                               entityName = arr[0].name ?? "";
+                               entityGuid = arr[0].guid ?? "";
+                       } else if (!Array.isArray(arr) && arr?.name) {
+                               entityName = arr.name;
+                               entityGuid = arr.guid ?? "";
+                       }
+               }
+       } catch {
+               /* ignore */
+       }
+
+       return { typeLabel, entityName, entityGuid, actionPhrase, user, dateStr 
};
+};
+
+const getDetailUrl = (
+       operation: string | undefined,
+       params: string,
+       entityName: string,
+       entityGuid: string
+): string | null => {
+       if ((operation === "PURGE" || operation === "AUTO_PURGE") && 
entityGuid) {
+               return `/detailPage/${entityGuid}`;
+       }
+       if (!entityName && !entityGuid) return null;
+       /* Type Created/Updated/Deleted tabs - link to type details */
+       const param = params?.split(",")[0]?.trim();
+       if (param === "CLASSIFICATION") {
+               return `/tag/tagAttribute/${entityName}`;
+       }
+       if (param === "BUSINESS_METADATA" && entityGuid) {
+               return `/administrator/businessMetadata/${entityGuid}`;
+       }
+       if (["ENTITY", "ENUM", "RELATIONSHIP", "STRUCT"].includes(param ?? "")) 
{
+               return null;
+       }
+       return `/administrator?tabActive=typeSystem`;
+};
+
+const RecentActivity = memo(() => {
+       const dashboardRefreshVersion = useAppSelector((state) => 
state.dashboardRefresh.version);
+       const navigate = useNavigate();
+       const [activeTab, setActiveTab] = useState(0);
+       const [tabData, setTabData] = useState<Record<string, AuditRecord[]>>({
+               typeCreated: [],
+               typeUpdated: [],
+               typeDeleted: [],
+               purge: [],
+               import: [],
+               export: []
+       });
+       const [loading, setLoading] = useState<Record<string, boolean>>({
+               typeCreated: false,
+               typeUpdated: false,
+               typeDeleted: false,
+               purge: false,
+               import: false,
+               export: false
+       });
+
+       const fetchAudits = useCallback(async (tabId: string, operations: 
string[]) => {
+               setLoading((prev) => ({ ...prev, [tabId]: true }));
+               try {
+                       const allResults: AuditRecord[] = [];
+                       for (const op of operations) {
+                               const auditFilters = {
+                                       condition: "AND" as const,
+                                       criterion: [
+                                               {
+                                                       attributeName: 
"operation",
+                                                       operator: "eq" as const,
+                                                       attributeValue: op
+                                               }
+                                       ]
+                               };
+                               const resp = await getAuditData({
+                                       auditFilters,
+                                       limit: 5,
+                                       offset: 0,
+                                       sortBy: "startTime",
+                                       sortOrder: "DESCENDING"
+                               });
+                               const data = (resp as { data?: AuditRecord[] 
})?.data ?? [];
+                               if (Array.isArray(data)) 
allResults.push(...data);
+                       }
+                       allResults.sort((a, b) => (b.endTime ?? 0) - (a.endTime 
?? 0));
+                       setTabData((prev) => ({ ...prev, [tabId]: 
allResults.slice(0, 5) }));
+               } catch {
+                       setTabData((prev) => ({ ...prev, [tabId]: [] }));
+               } finally {
+                       setLoading((prev) => ({ ...prev, [tabId]: false }));
+               }
+       }, []);
+
+       useEffect(() => {
+               AUDIT_TABS.forEach((tab) => {
+                       fetchAudits(tab.id, [...tab.operations]);
+               });
+       }, [fetchAudits, dashboardRefreshVersion]);
+
+       const handleViewAll = useCallback(() => {
+               navigate("/administrator?tabActive=audit");
+       }, [navigate]);
+
+       const handleTabChange = useCallback((_: React.SyntheticEvent, newValue: 
number) => {
+               setActiveTab(newValue);
+       }, []);
+
+       const currentTab = AUDIT_TABS[activeTab];
+       const records = tabData[currentTab?.id] ?? [];
+       const isLoading = loading[currentTab?.id] ?? false;
+
+       const [typeDetailOpen, setTypeDetailOpen] = useState(false);
+       const [typeDetailObject, setTypeDetailObject] = useState<Record<string, 
unknown> | null>(null);
+
+       const handleCloseTypeDetail = useCallback(() => {
+               setTypeDetailOpen(false);
+               setTypeDetailObject(null);
+       }, []);
+
+       const handleOpenTypeDetail = useCallback((obj: Record<string, unknown>) 
=> {
+               setTypeDetailObject(obj);
+               setTypeDetailOpen(true);
+       }, []);
+
+       return (
+               <Paper
+                       elevation={1}
+                       sx={{
+                               padding: 2,
+                               borderRadius: 2,
+                               minHeight: 280,
+                               width: "100%",
+                               boxSizing: "border-box",
+                               transition: "box-shadow 0.3s ease",
+                               "&:hover": { boxShadow: 4 }
+                       }}
+               >
+                       <Box sx={{ pb: 2, borderBottom: "1px solid", 
borderColor: "divider" }}>
+                               <Stack direction="row" 
justifyContent="space-between" alignItems="center">
+                                       <Typography sx={{ fontSize: "1rem", 
fontWeight: 600, color: "#1a1a1a" }}>
+                                               Recent Activity
+                                       </Typography>
+                                       <Link
+                                               component="button"
+                                               onClick={handleViewAll}
+                                               sx={{
+                                                       fontSize: "0.875rem",
+                                                       cursor: "pointer",
+                                                       textDecoration: "none",
+                                                       color: "primary.main"
+                                               }}
+                                               aria-label="View all audits"
+                                       >
+                                               View All
+                                       </Link>
+                               </Stack>
+                       </Box>
+                       <Stack direction="row" spacing={1} sx={{ mt: 1.5, 
flexWrap: "wrap", gap: 1 }}>
+                               {AUDIT_TABS.map((tab, idx) => (
+                                       <Chip
+                                               key={tab.id}
+                                               label={tab.label}
+                                               onClick={(e) => 
handleTabChange(e as unknown as React.SyntheticEvent, idx)}
+                                               color={activeTab === idx ? 
"primary" : "default"}
+                                               variant={activeTab === idx ? 
"filled" : "outlined"}
+                                               sx={{
+                                                       fontSize: "0.8125rem",
+                                                       height: 32,
+                                                       "&.MuiChip-filled": { 
fontWeight: 600 }
+                                               }}
+                                               aria-pressed={activeTab === idx}
+                                               aria-label={`${tab.label} tab`}
+                                       />
+                               ))}
+                       </Stack>
+                       <Box sx={{ pt: 1 }}>
+                               {isLoading ? (
+                                       <RecentActivityListSkeleton />
+                               ) : isEmpty(records) ? (
+                                       <Stack alignItems="center" 
justifyContent="center" height={180}>
+                                               <Typography variant="body2" 
color="text.secondary">
+                                                       No records present
+                                               </Typography>
+                                       </Stack>
+                               ) : (
+                                       <List disablePadding>
+                                               {records.map((record, idx) => {
+                                                       const parsed = 
parseAuditRecord(record);
+                                                       const { typeLabel, 
entityName, entityGuid, actionPhrase, user, dateStr } = parsed;
+                                                       const typeDefPayload = 
extractTypeDefDetailObject(
+                                                               record,
+                                                               entityName ?? 
"",
+                                                               entityGuid ?? ""
+                                                       );
+                                                       const detailUrl = 
getDetailUrl(
+                                                               
record.operation ?? "",
+                                                               record.params 
?? "",
+                                                               entityName ?? 
"",
+                                                               entityGuid ?? ""
+                                                       );
+
+                                                       const 
openTypeModalIfNeeded = () => {
+                                                               if 
(typeDefPayload) {
+                                                                       
handleOpenTypeDetail(typeDefPayload);
+                                                               }
+                                                       };
+
+                                                       const 
handleEntityNameKeyDown = (
+                                                               e: 
React.KeyboardEvent
+                                                       ) => {
+                                                               if (e.key !== 
"Enter" && e.key !== " ") return;
+                                                               
e.preventDefault();
+                                                               
openTypeModalIfNeeded();
+                                                       };
+
+                                                       return (
+                                                               <ListItem
+                                                                       
key={record.guid ?? idx}
+                                                                       
disablePadding
+                                                                       sx={{
+                                                                               
py: 1,
+                                                                               
borderBottom: "1px solid",
+                                                                               
borderColor: "divider",
+                                                                               
"&:last-child": { borderBottom: "none" }
+                                                                       }}
+                                                               >
+                                                                       
<Typography component="span" sx={{ fontSize: "0.875rem", color: "#333" }}>
+                                                                               
{entityName ? (
+                                                                               
        <>
+                                                                               
                {typeDefPayload ? (
+                                                                               
                        <Link
+                                                                               
                                component="button"
+                                                                               
                                type="button"
+                                                                               
                                onClick={openTypeModalIfNeeded}
+                                                                               
                                onKeyDown={handleEntityNameKeyDown}
+                                                                               
                                tabIndex={0}
+                                                                               
                                aria-label={`Open ${typeLabel} type details for 
${entityName}`}
+                                                                               
                                sx={{
+                                                                               
                                        color: "primary.main",
+                                                                               
                                        textDecoration: "none",
+                                                                               
                                        background: "none",
+                                                                               
                                        border: "none",
+                                                                               
                                        cursor: "pointer",
+                                                                               
                                        padding: 0,
+                                                                               
                                        font: "inherit",
+                                                                               
                                        "&:hover": { textDecoration: 
"underline" },
+                                                                               
                                }}
+                                                                               
                        >
+                                                                               
                                {entityName}
+                                                                               
                        </Link>
+                                                                               
                ) : detailUrl ? (
+                                                                               
                        <Link
+                                                                               
                                component={RouterLink}
+                                                                               
                                to={detailUrl}
+                                                                               
                                sx={{
+                                                                               
                                        color: "primary.main",
+                                                                               
                                        textDecoration: "none",
+                                                                               
                                        "&:hover": { textDecoration: 
"underline" }
+                                                                               
                                }}
+                                                                               
                        >
+                                                                               
                                {entityName}
+                                                                               
                        </Link>
+                                                                               
                ) : (
+                                                                               
                        entityName
+                                                                               
                )}
+                                                                               
                {" "}
+                                                                               
                {typeLabel} {actionPhrase} by{" "}
+                                                                               
                <Box component="span" sx={{ fontWeight: 700 }}>
+                                                                               
                        {user}
+                                                                               
                </Box>{" "}
+                                                                               
                on{" "}
+                                                                               
                <Box component="span" sx={{ color: "#6c757d" }}>
+                                                                               
                        {dateStr}
+                                                                               
                </Box>
+                                                                               
        </>
+                                                                               
) : (
+                                                                               
        <>
+                                                                               
                {typeLabel} {actionPhrase} by{" "}
+                                                                               
                <Box component="span" sx={{ fontWeight: 700 }}>
+                                                                               
                        {user}
+                                                                               
                </Box>{" "}
+                                                                               
                on{" "}
+                                                                               
                <Box component="span" sx={{ color: "#6c757d" }}>
+                                                                               
                        {dateStr}
+                                                                               
                </Box>
+                                                                               
        </>
+                                                                               
)}
+                                                                       
</Typography>
+                                                               </ListItem>
+                                                       );
+                                               })}
+                                       </List>
+                               )}
+                       </Box>
+                       <TypeDefAuditDetailModal
+                               open={typeDetailOpen}
+                               onClose={handleCloseTypeDetail}
+                               detailObject={typeDetailObject}
+                       />
+               </Paper>
+       );
+});
+
+RecentActivity.displayName = "RecentActivity";
+
+export default RecentActivity;
diff --git a/dashboard/src/views/DashboardOverview/RecentActivitySkeleton.tsx 
b/dashboard/src/views/DashboardOverview/RecentActivitySkeleton.tsx
new file mode 100644
index 000000000..8ca10811f
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/RecentActivitySkeleton.tsx
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Stack } from "@mui/material";
+import SkeletonLoader from "@components/SkeletonLoader";
+
+/** Shown inside Recent Activity while the active tab's audits are loading. */
+export const RecentActivityListSkeleton = () => (
+       <Stack spacing={1.5} sx={{ pt: 1 }}>
+               {[1, 2, 3, 4, 5].map((i) => (
+                       <SkeletonLoader
+                               key={i}
+                               animation="wave"
+                               variant="text"
+                               count={1}
+                               width={`${85 - i * 5}%`}
+                               height={20}
+                       />
+               ))}
+       </Stack>
+);
+
+export default RecentActivityListSkeleton;
diff --git a/dashboard/src/views/DashboardOverview/dashboardChartPalette.ts 
b/dashboard/src/views/DashboardOverview/dashboardChartPalette.ts
new file mode 100644
index 000000000..fb012a445
--- /dev/null
+++ b/dashboard/src/views/DashboardOverview/dashboardChartPalette.ts
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Matches Entity Status Overview donut — single source for dashboard charts 
*/
+export const ENTITY_STATUS_DONUT_COLORS = {
+       Active: "#10b981",
+       Shell: "#f59e0b",
+       Deleted: "#ef4444",
+} as const;
+
+/** Active primary series / bar fill (aligned with Classification Distribution 
bars) */
+export const CHART_BAR_ACTIVE_BLUE = "#1976d2";
+
+/** Horizontal bar charts: Y-axis title + ticks; keep left tight to reduce 
card gutter */
+export const HORIZONTAL_BAR_CHART_MARGIN = {
+       top: 8,
+       right: 72,
+       left: 44,
+       bottom: 48,
+} as const;
+
+/** Tighter layout: short classification names — minimize dead space left of Y 
ticks */
+export const CLASSIFICATION_DISTRIBUTION_CHART_MARGIN = {
+       top: 8,
+       right: 72,
+       left: 12,
+       bottom: 48,
+} as const;

Reply via email to