diff --git a/src/app/(private)/data-sources/components/UserDataSourcesList.tsx b/src/app/(private)/data-sources/components/UserDataSourcesList.tsx index dd0ededc..a3f3d137 100644 --- a/src/app/(private)/data-sources/components/UserDataSourcesList.tsx +++ b/src/app/(private)/data-sources/components/UserDataSourcesList.tsx @@ -1,9 +1,7 @@ "use client"; -import { Boxes, Database, PlusIcon, Users } from "lucide-react"; +import { Boxes, Database, PlusIcon, Users, UsersIcon } from "lucide-react"; import { useMemo, useState } from "react"; -import { CollectionIcon } from "@/app/map/[id]/components/Icons"; -import { mapColors } from "@/app/map/[id]/styles"; import { DataSourceItem } from "@/components/DataSourceItem"; import DataSourceRecordTypeIcon, { dataSourceRecordTypeColors, @@ -30,17 +28,39 @@ export default function UserDataSourcesList({ const memberDataSources = useMemo( () => - dataSources?.filter( - (dataSource) => dataSource.recordType === DataSourceRecordType.Members, - ), + dataSources + ?.filter( + (dataSource) => + dataSource.recordType === DataSourceRecordType.Members, + ) + .sort((a, b) => { + const aDate = a.importInfo?.lastCompleted + ? new Date(a.importInfo.lastCompleted).getTime() + : 0; + const bDate = b.importInfo?.lastCompleted + ? new Date(b.importInfo.lastCompleted).getTime() + : 0; + return bDate - aDate; // Most recent first + }), [dataSources], ); const otherDataSources = useMemo( () => - dataSources?.filter( - (dataSource) => dataSource.recordType !== DataSourceRecordType.Members, - ), + dataSources + ?.filter( + (dataSource) => + dataSource.recordType !== DataSourceRecordType.Members, + ) + .sort((a, b) => { + const aDate = a.importInfo?.lastCompleted + ? new Date(a.importInfo.lastCompleted).getTime() + : 0; + const bDate = b.importInfo?.lastCompleted + ? new Date(b.importInfo.lastCompleted).getTime() + : 0; + return bDate - aDate; // Most recent first + }), [dataSources], ); @@ -96,8 +116,8 @@ export default function UserDataSourcesList({ {/* Member Collections Section */}
-

- +

+ Member data sources

@@ -122,8 +142,7 @@ export default function UserDataSourcesList({ {/* Other Data Sources Section */}
-

- +

Other data sources

diff --git a/src/components/DataSourceItem.tsx b/src/components/DataSourceItem.tsx index 4a84f4ff..a578b93a 100644 --- a/src/components/DataSourceItem.tsx +++ b/src/components/DataSourceItem.tsx @@ -1,8 +1,8 @@ import { formatDistanceToNow } from "date-fns"; import { Database, RefreshCw } from "lucide-react"; import DataSourceIcon from "@/components/DataSourceIcon"; -import { DataSourceType } from "@/server/models/DataSource"; import { cn } from "@/shadcn/utils"; +import type { DataSourceType } from "@/server/models/DataSource"; import type { RouterOutputs } from "@/services/trpc/react"; export type DataSourceWithImportInfo = NonNullable< @@ -67,15 +67,15 @@ const getDataSourceStyle = (type: DataSourceType | "unknown") => { const getGeocodingStatus = (dataSource: DataSourceWithImportInfo) => { const geocodingConfig = dataSource.geocodingConfig; if (geocodingConfig.type === "None") { - return { status: "No geocoding", color: "text-neutral-500" }; + return { status: "No geocoding", color: "text-neutral-400" }; } if (geocodingConfig.type === "Address") { - return { status: "Address geocoding", color: "text-green-600" }; + return { status: "Address geocoding", color: "text-neutral-400" }; } if (geocodingConfig.type === "Code" || geocodingConfig.type === "Name") { - return { status: "Area-based geocoding", color: "text-blue-600" }; + return { status: "Area-based geocoding", color: "text-neutral-400" }; } - return { status: "Geocoding configured", color: "text-blue-600" }; + return { status: "Geocoding configured", color: "text-neutral-400" }; }; export function DataSourceItem({ @@ -96,62 +96,62 @@ export function DataSourceItem({ return (
-
- {/* Icon */} - - - {/* Content */} -
- {/* Header */} -
-
-

{dataSource.name}

-
- -
- {dataSource.public && ( - - Public - - )} - {lastImportedText && ( - - - {lastImportedText} - - )} -
-
+ {/* Header: Icon and Name */} +
+
+ +

{dataSourceType}

+ {lastImportedText && ( + + + {lastImportedText} + + )}
- {/* Stats */} -
- {dataSource.columnDefs.length} columns - - {dataSource.recordCount || "Unknown"} records - - {geocodingStatus.status} +
+

+ {dataSource.name} +

- {/* Type-specific info */} - {dataSourceType === DataSourceType.ActionNetwork && ( - - Activist engagement data - - )} - {dataSourceType === DataSourceType.Mailchimp && ( - Email subscriber data - )} - {dataSource.autoImport && ( - - - Auto-import enabled - - )} + {/* Metadata: Consolidated stats and status */} +
+ {/* Primary stats: Records, columns, and last updated */} +
+ + {dataSource.recordCount?.toLocaleString() || "Unknown"} records + + + + {dataSource.columnDefs.length} columns + +
+ + {/* Secondary info: Geocoding (muted) and status badges */} +
+ + {geocodingStatus.status} + + + {dataSource.public && ( + + Public + + )} + + {dataSource.autoImport && ( + + + Auto-import + + )} +
+
); }