feat: add repository pattern, service layer architecture, and scheduler management

- Implement repository pattern for data access layer
- Add comprehensive service layer for business logic
- Create scheduler management system with health monitoring
- Add bounded buffer utility for memory management
- Enhance security audit logging with retention policies
This commit is contained in:
2025-07-12 07:00:37 +02:00
parent e1abedb148
commit 041a1cc3ef
54 changed files with 5755 additions and 878 deletions

View File

@ -15,7 +15,7 @@ export default function CompanySettingsPage() {
const csvUsernameId = useId();
const csvPasswordId = useId();
const { data: session, status } = useSession();
const [_company, setCompany] = useState<Company | null>(null);
const [, setCompany] = useState<Company | null>(null);
const [csvUrl, setCsvUrl] = useState<string>("");
const [csvUsername, setCsvUsername] = useState<string>("");
const [csvPassword, setCsvPassword] = useState<string>("");

View File

@ -470,7 +470,7 @@ function DashboardContent() {
const { data: session, status } = useSession();
const router = useRouter();
const [metrics, setMetrics] = useState<MetricsResult | null>(null);
const [company, _setCompany] = useState<Company | null>(null);
const [company] = useState<Company | null>(null);
const [refreshing, setRefreshing] = useState<boolean>(false);
const [isInitialLoad, setIsInitialLoad] = useState<boolean>(true);
@ -505,27 +505,28 @@ function DashboardContent() {
avgSessionLength: null,
days: {},
languages: {},
categories: {},
countries: {},
belowThresholdCount: 0,
// Map sentiment data to individual counts
sentimentPositiveCount:
overviewData.sentimentDistribution?.find(
(s) => s.sentiment === "positive"
(s) => s.sentiment === "POSITIVE"
)?.count || 0,
sentimentNeutralCount:
overviewData.sentimentDistribution?.find(
(s) => s.sentiment === "neutral"
(s) => s.sentiment === "NEUTRAL"
)?.count || 0,
sentimentNegativeCount:
overviewData.sentimentDistribution?.find(
(s) => s.sentiment === "negative"
(s) => s.sentiment === "NEGATIVE"
)?.count || 0,
// Map category data to CategoryMetrics format
...(overviewData.categoryDistribution && {
categories: overviewData.categoryDistribution.reduce(
(acc, item) => {
acc[item.category] = item.count;
if (item.category) {
acc[item.category] = item.count;
}
return acc;
},
{} as Record<string, number>

View File

@ -32,21 +32,21 @@ interface FilterOptions {
interface FilterSectionProps {
filtersExpanded: boolean;
setFiltersExpanded: (_expanded: boolean) => void;
setFiltersExpanded: (expanded: boolean) => void;
searchTerm: string;
setSearchTerm: (_term: string) => void;
setSearchTerm: (term: string) => void;
selectedCategory: string;
setSelectedCategory: (_category: string) => void;
setSelectedCategory: (category: string) => void;
selectedLanguage: string;
setSelectedLanguage: (_language: string) => void;
setSelectedLanguage: (language: string) => void;
startDate: string;
setStartDate: (_date: string) => void;
setStartDate: (date: string) => void;
endDate: string;
setEndDate: (_date: string) => void;
setEndDate: (date: string) => void;
sortKey: string;
setSortKey: (_key: string) => void;
setSortKey: (key: string) => void;
sortOrder: string;
setSortOrder: (_order: string) => void;
setSortOrder: (order: string) => void;
filterOptions: FilterOptions;
searchHeadingId: string;
searchId: string;
@ -392,7 +392,7 @@ function SessionList({
interface PaginationProps {
currentPage: number;
totalPages: number;
setCurrentPage: (_page: number | ((_prev: number) => number)) => void;
setCurrentPage: (page: number | ((prev: number) => number)) => void;
}
function Pagination({