appender events and applications are updated

This commit is contained in:
2025-05-06 12:03:58 +03:00
parent dd707b2463
commit e0ae1ee80a
53 changed files with 2358 additions and 829 deletions

View File

@@ -1,87 +1,198 @@
"use server";
import { fetchDataWithToken } from "../api-fetcher";
import { baseUrlApplication } from "../basics";
import { PaginationParams } from "../schemas/list";
import type { PaginatedApiResponse } from "@/app/api/utils/types";
import {
collectPaginationFromApiResponse,
defaultPaginationResponse,
type PaginatedApiResponse
} from "@/app/api/utils/types";
const applicationListEndpoint = `${baseUrlApplication}/application/list/all`;
const applicationListAvailableEndpoint = `${baseUrlApplication}/application/list/available`;
const applicationListAppendedEndpoint = `${baseUrlApplication}/application/list/appended`;
const applicationRegisterServiceEndpoint = `${baseUrlApplication}/application/register/service`;
const applicationUnregisterServiceEndpoint = `${baseUrlApplication}/application/unregister/service`;
const applicationListEndpoint = `${baseUrlApplication}/application/list`;
const applicationUpdateEndpoint = `${baseUrlApplication}/application/update`;
const applicationCreateEndpoint = `${baseUrlApplication}/application/create`;
const applicationDeleteEndpoint = `${baseUrlApplication}/application/delete`;
interface AppendApplicationToService {
application_uu_id: string;
service_uu_id: string;
}
interface RemoveApplicationFromService extends AppendApplicationToService { }
async function listApplicationsAvailable(payload: PaginationParams): Promise<PaginatedApiResponse<any>> {
if (!payload.query.service_uu_id__ilike) {
console.warn('Missing service_uu_id in query parameters');
return {
data: [],
pagination: defaultPaginationResponse,
};
}
async function listApplications(payload: PaginationParams): Promise<PaginatedApiResponse<any>> {
try {
const requestBody = {
page: payload.page,
size: payload.size,
order_field: payload.orderField,
order_type: payload.orderType,
query: payload.query,
};
console.log('Sending request to backend with service_uu_id:', payload.query.service_uu_id);
console.log('Full request body:', JSON.stringify(requestBody, null, 2));
const response = await fetchDataWithToken(
applicationListEndpoint,
{
page: payload.page,
size: payload.size,
order_field: payload.orderField,
order_type: payload.orderType,
query: payload.query,
},
applicationListAvailableEndpoint,
requestBody,
"POST",
false
);
if (response?.status === 200 || response?.status === 202) {
const responseData = response.data as any;
const responseData = response.data as PaginatedApiResponse<any>;
console.log('list_events_available responseData:', JSON.stringify(responseData, null, 2));
return {
data: responseData.data || [],
pagination: {
page: responseData.pagination?.page || 1,
size: responseData.pagination?.size || 10,
totalCount: responseData.pagination?.totalCount || 0,
totalItems: responseData.pagination?.totalItems || 0,
totalPages: responseData.pagination?.totalPages || 0,
pageCount: responseData.pagination?.pageCount || 0,
orderField: responseData.pagination?.orderField || ['name'],
orderType: responseData.pagination?.orderType || ['asc'],
query: responseData.pagination?.query || {},
next: responseData.pagination?.next || false,
back: responseData.pagination?.back || false
}
pagination: collectPaginationFromApiResponse(responseData)
};
}
return {
data: [],
pagination: {
page: 1,
size: 10,
totalCount: 0,
totalItems: 0,
totalPages: 0,
pageCount: 0,
orderField: ['name'],
orderType: ['asc'],
query: {},
next: false,
back: false
}
pagination: defaultPaginationResponse,
};
} catch (error) {
console.error("Error fetching application list:", error);
console.error("Error fetching events list:", error);
return {
data: [],
pagination: {
page: 1,
size: 10,
totalCount: 0,
totalItems: 0,
totalPages: 0,
pageCount: 0,
orderField: ['name'],
orderType: ['asc'],
query: {},
next: false,
back: false
}
pagination: defaultPaginationResponse,
};
}
}
async function listApplicationsAppended(payload: PaginationParams): Promise<PaginatedApiResponse<any>> {
if (!payload.query.service_uu_id__ilike) {
console.warn('Missing service_uu_id in query parameters');
return {
data: [],
pagination: defaultPaginationResponse,
};
}
try {
const requestBody = {
page: payload.page,
size: payload.size,
order_field: payload.orderField,
order_type: payload.orderType,
query: payload.query,
};
console.log('Sending request to backend with service_uu_id:', payload.query.service_uu_id);
console.log('Full request body:', JSON.stringify(requestBody, null, 2));
const response = await fetchDataWithToken(
applicationListAppendedEndpoint,
requestBody,
"POST",
false
);
if (response?.status === 200 || response?.status === 202) {
const responseData = response.data as PaginatedApiResponse<any>;
console.log('list_events_available responseData:', JSON.stringify(responseData, null, 2));
return {
data: responseData.data || [],
pagination: collectPaginationFromApiResponse(responseData)
};
}
return {
data: [],
pagination: defaultPaginationResponse,
};
} catch (error) {
console.error("Error fetching events list:", error);
return {
data: [],
pagination: defaultPaginationResponse,
};
}
}
async function listAllApplications(payload: PaginationParams): Promise<PaginatedApiResponse<any>> {
try {
const requestBody = {
page: payload.page,
size: payload.size,
order_field: payload.orderField,
order_type: payload.orderType,
query: payload.query,
};
console.log('Sending request to backend with service_uu_id:', payload.query.service_uu_id);
console.log('Full request body:', JSON.stringify(requestBody, null, 2));
const response = await fetchDataWithToken(
applicationListEndpoint,
requestBody,
"POST",
false
);
if (response?.status === 200 || response?.status === 202) {
const responseData = response.data as PaginatedApiResponse<any>;
console.log('list_events_available responseData:', JSON.stringify(responseData, null, 2));
return {
data: responseData.data || [],
pagination: collectPaginationFromApiResponse(responseData)
};
}
return {
data: [],
pagination: defaultPaginationResponse,
};
} catch (error) {
console.error("Error fetching events list:", error);
return {
data: [],
pagination: defaultPaginationResponse,
};
}
}
async function appendApplicationToService(payload: AppendApplicationToService) {
try {
const response = await fetchDataWithToken(
applicationRegisterServiceEndpoint,
payload,
"POST",
false
);
return response?.status === 200 || response?.status === 202 ? response.data : null;
} catch (error) {
console.error("Error appending event to service:", error);
}
}
async function removeApplicationFromService(payload: RemoveApplicationFromService) {
try {
const response = await fetchDataWithToken(
applicationUnregisterServiceEndpoint,
payload,
"POST",
false
);
return response?.status === 200 || response?.status === 202 ? response.data : null;
} catch (error) {
console.error("Error removing event from service:", error);
}
}
async function createApplication(payload: any) {
try {
const response = await fetchDataWithToken(
@@ -100,6 +211,7 @@ async function createApplication(payload: any) {
}
async function updateApplication(payload: any, uuId: string) {
console.log("Updating application with payload:", payload, 'uuId:', uuId);
try {
const response = await fetchDataWithToken(
`${applicationUpdateEndpoint}/${uuId}`,
@@ -134,7 +246,11 @@ async function deleteApplication(uuId: string) {
}
export {
listApplications,
listApplicationsAvailable,
listApplicationsAppended,
listAllApplications,
appendApplicationToService,
removeApplicationFromService,
createApplication,
updateApplication,
deleteApplication,

View File

@@ -0,0 +1,22 @@
import { appendApplicationToService } from "@/apicalls/application/endpoints";
import { NextRequest } from "next/server";
import { withErrorHandling } from "@/app/api/utils/requestHandlers";
import {
successResponse,
errorResponse,
} from "@/app/api/utils/responseHandlers";
export const POST = withErrorHandling(
async (request: NextRequest, body: any) => {
const payload = {
application_uu_id: body.application_uu_id,
service_uu_id: body.service_uu_id,
};
const result = await appendApplicationToService(payload);
if (!result) {
return errorResponse("Error appending application to service");
} else {
return successResponse(result);
}
}
);

View File

@@ -0,0 +1,22 @@
import { removeApplicationFromService } from "@/apicalls/application/endpoints";
import { NextRequest } from "next/server";
import { withErrorHandling } from "@/app/api/utils/requestHandlers";
import {
successResponse,
errorResponse,
} from "@/app/api/utils/responseHandlers";
export const POST = withErrorHandling(
async (request: NextRequest, body: any) => {
const payload = {
application_uu_id: body.application_uu_id,
service_uu_id: body.service_uu_id,
};
const result = await removeApplicationFromService(payload);
if (!result) {
return errorResponse("Error removing application from service");
} else {
return successResponse(result);
}
}
);

View File

@@ -0,0 +1,4 @@
import { listApplicationsAppended } from "@/apicalls/application/endpoints";
import { createListHandler } from "@/app/api/utils/apiOperations";
export const POST = createListHandler(listApplicationsAppended);

View File

@@ -0,0 +1,4 @@
import { createCreateHandler } from "@/app/api/utils";
import { appendApplicationToService } from "@/apicalls/application/endpoints";
export const POST = createCreateHandler(appendApplicationToService);

View File

@@ -1,4 +1,4 @@
import { listApplications } from "@/apicalls/application/endpoints";
import { listApplicationsAvailable } from "@/apicalls/application/endpoints";
import { createListHandler } from "@/app/api/utils";
export const POST = createListHandler(listApplications);
export const POST = createListHandler(listApplicationsAvailable);

View File

@@ -0,0 +1,4 @@
import { listAllApplications } from "@/apicalls/application/endpoints";
import { createListHandler } from "@/app/api/utils";
export const POST = createListHandler(listAllApplications);

View File

@@ -0,0 +1,4 @@
import { createCreateHandler } from "@/app/api/utils";
import { removeApplicationFromService } from "@/apicalls/application/endpoints";
export const POST = createCreateHandler(removeApplicationFromService);

View File

@@ -167,7 +167,7 @@ export function UpdateComponent<T>({
console.error("API URL is missing or undefined");
return;
}
const uuid = initialData ? (initialData as any).uuid || (initialData as any).uu_id : null;
const uuid = initialData ? (initialData as any).uu_id : null;
if (!uuid) {
console.error("UUID not found in initialData");
throw new Error("UUID is required for update operations");
@@ -181,6 +181,7 @@ export function UpdateComponent<T>({
});
const updateUrl = `${apiUrl}/update?uuid=${uuid}`;
console.log("Updating application with payload:", dataToSend, 'uuId:', uuid);
try {
let response = await fetch(updateUrl, {
method: 'POST',

View File

@@ -0,0 +1,15 @@
import React from 'react'
const Loader = () => {
return (
<>
<div className="flex-1">
<div className="flex items-center justify-center h-40 bg-gray-100 rounded-md">
<div className="animate-spin rounded-full h-10 w-10 border-b-2 border-primary"></div>
</div>
</div>
</>
)
}
export default Loader

View File

@@ -1,5 +1,6 @@
import { useDataFetching, ApiResponse } from "./useDataFetching";
import { RequestParams } from "../schemas";
import { defaultPaginationResponse } from "@/app/api/utils/types";
/**
* Hook for fetching data from Next.js API routes
@@ -23,8 +24,7 @@ export function useApiData<T>(
query: params.query,
};
const listEndpoint = `${endpoint}/list`;
const response = await fetch(listEndpoint, {
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -42,19 +42,7 @@ export function useApiData<T>(
return {
data: [],
pagination: {
page: params.page,
size: params.size,
totalCount: 0,
totalItems: 0,
totalPages: 0,
pageCount: 0,
orderField: params.orderField,
orderType: params.orderType,
query: params.query,
next: false,
back: false,
},
pagination: defaultPaginationResponse,
};
}
};

View File

@@ -0,0 +1,168 @@
import {
LanguageKey,
TranslationSet,
} from "@/validations/translations/translation";
import {
ServiceBaseTranslationEn,
ServiceBaseTranslationTr,
} from "./schemaList/services";
import {
ApplicationBaseTranslationTr,
ApplicationBaseTranslationEn,
} from "./schemaList/application";
const translations = {
en: {
// Page title
mainTitle: "Services",
// Common actions
create: "Create",
update: "Update",
delete: "Delete",
view: "View",
save: "Save",
cancel: "Cancel",
// Search and filters
search: "Search",
typeSelection: "Type Selection",
filterSelection: "Filter Selection",
siteUrl: "Site URL",
resetAll: "Reset All",
// Type options
web: "Web",
mobile: "Mobile",
// Status options
status: "Status",
active: "Active",
inactive: "Inactive",
pending: "Pending",
// User types
employee: "Employee",
occupant: "Occupant",
// Pagination
showing: "Showing",
of: "of",
items: "items",
total: "Total",
filtered: "Filtered",
previous: "Previous",
next: "Next",
page: "Page",
itemsPerPage: "Items per page",
// Messages
noData: "No data found",
serviceSelectedTitle: "Selected Service",
serviceSelectedContent: "is selected to appende events",
// Other
applicationType: "Application Type",
availableApplications: "Available Applications",
code: "Code",
sortBy: "Sort by:",
formErrors: "Please correct the errors in the form",
// Form group titles
identificationInfo: "Identification Information",
applicationDetails: "Application Details",
statusInfo: "Status Information",
systemInfo: "System Information",
createDescription: "Create Application",
},
tr: {
// Page title
mainTitle: "Servisler",
// Common actions
create: "Oluştur",
update: "Güncelle",
delete: "Sil",
view: "Görüntüle",
save: "Kaydet",
cancel: "İptal",
// Search and filters
search: "Ara",
typeSelection: "Tür Seçimi",
filterSelection: "Filtre Seçimi",
siteUrl: "Site URL",
resetAll: "Tümünü Sıfırla",
// Type options
web: "Web",
mobile: "Mobil",
// Status options
status: "Durum",
active: "Aktif",
inactive: "Pasif",
pending: "Beklemede",
// User types
employee: "Çalışan",
occupant: "Sakin",
// Pagination
showing: "Gösteriliyor",
of: "of",
items: "öğeler",
total: "Toplam",
filtered: "Filtreli",
previous: "Önceki",
next: "Sonraki",
page: "Sayfa",
itemsPerPage: "Sayfa başına öğeler",
// Messages
noData: "Veri bulunamadı",
serviceSelectedTitle: "Seçili Servis",
serviceSelectedContent: "is selected to appende events",
// Other
applicationType: "Uygulama Türü",
availableApplications: "Mevcut Uygulamalar",
code: "Kod",
sortBy: "Sırala:",
formErrors: "Lütfen formdaki hataları düzeltiniz",
// Form group titles
identificationInfo: "Kimlik Bilgileri",
applicationDetails: "Uygulama Detayları",
statusInfo: "Durum Bilgileri",
systemInfo: "Sistem Bilgileri",
createDescription: "Yeni bir uygulama oluşturun",
},
};
const translationsServices = {
en: {
...translations.en,
...ServiceBaseTranslationEn,
},
tr: {
...translations.tr,
...ServiceBaseTranslationTr,
},
};
const translationsApplications = {
en: {
...translations.en,
...ApplicationBaseTranslationEn,
},
tr: {
...translations.tr,
...ApplicationBaseTranslationTr,
},
};
export { translations, translationsServices, translationsApplications };
export function getTranslation(lang: LanguageKey): TranslationSet {
return translations[lang];
}

View File

@@ -0,0 +1,372 @@
"use client";
import React, { useState, useEffect } from "react";
import { z } from "zod";
import {
ServiceData,
serviceViewFieldDefinitions,
ServiceFieldDefinitionsType,
ServiceSchema,
serviceFieldsByMode,
} from "./schemaList/services";
import {
ApplicationData,
ApplicationFieldDefinitionsType,
ApplicationSchema,
applicationFieldsByMode,
applicationViewFieldDefinitions
} from "./schemaList/application";
import { ListComponentEvents, ListComponentServices } from "./listComponent";
import { translations, translationsServices, translationsApplications } from "./language";
import { PageProps } from "@/validations/translations/translation";
import { FormModeView, FormMode } from "@/components/common/FormDisplay/types";
import { FormDisplay } from "@/components/common/FormDisplay/FormDisplay";
import { GridSelectionComponent, GridSize } from "@/components/common/HeaderSelections/GridSelectionComponent";
import { useApiData } from "@/components/common";
import { Language } from "@/components/common/schemas";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { CardSize } from "@/components/common/CardDisplay/schema";
import { translationsAppenders } from "../appendersEvents/language";
import Loader from "@/components/common/Loader/loader";
const AppendersApplicationPage: React.FC<PageProps> = ({ lang }: { lang: Language }) => {
const urlServices = '/api/services/list';
const urlEvents = '/api/applications/list';
const urlAppenders = '/api/appenders/applications/list';
const urlAppendersCreate = '/api/appenders/applications/create';
const urlAppendersDelete = '/api/appenders/applications/delete';
const showFieldsServices = ["service_name", "service_code", "related_responsibility"];
const showFieldsEvents = ["description", "name", "site_url", "application_code"];
const {
data: dataServices,
pagination: paginationServices,
loading: loadingServices,
error: errorServices,
updatePagination: updatePaginationServices,
refetch: refetchServices
} = useApiData<ServiceData>(urlServices);
const {
data: dataEvents,
pagination: paginationEvents,
loading: loadingEvents,
error: errorEvents,
updatePagination: updatePaginationEvents,
refetch: refetchEvents
} = useApiData<ApplicationData>(urlEvents);
const {
data: dataAppenders,
pagination: paginationAppenders,
loading: loadingAppenders,
error: errorAppenders,
updatePagination: updatePaginationAppenders,
refetch: refetchAppenders
} = useApiData<ApplicationData>(urlAppenders);
const [mode, setMode] = useState<FormModeView | FormMode>("list");
const [gridCols, setGridCols] = useState<GridSize>(3);
const [selectedItemServices, setSelectedItemServices] = useState<ServiceData | null>(null);
const [selectedItemEvents, setSelectedItemEvents] = useState<ApplicationData | null>(null);
const [selectedItemAppenders, setSelectedItemAppenders] = useState<ApplicationData | null>(null);
const [fieldDefinitionsServices, setFieldDefinitionsServices] = useState<ServiceFieldDefinitionsType | null>(null);
const [fieldDefinitionsEvents, setFieldDefinitionsEvents] = useState<ApplicationFieldDefinitionsType | null>(null);
const [fieldDefinitionsAppenders, setFieldDefinitionsAppenders] = useState<ApplicationFieldDefinitionsType | null>(null);
const [validationSchemaServices, setValidationSchemaServices] = useState<z.ZodSchema | null>(null);
const [validationSchemaEvents, setValidationSchemaEvents] = useState<z.ZodSchema | null>(null);
const [validationSchemaAppenders, setValidationSchemaAppenders] = useState<z.ZodSchema | null>(null);
const [selectionBar, setSelectionBar] = useState<string>("");
const [languageTranslations, setLanguageTranslations] = useState({
mainTitle: translations[lang].mainTitle,
serviceSelectedTitle: translations[lang].serviceSelectedTitle,
serviceSelectedContent: translations[lang].serviceSelectedContent,
cancel: translations[lang].cancel,
});
const appendServiceEvent = async (app: ApplicationData) => {
if (!selectedItemServices?.uu_id) {
throw new Error("Service not selected");
}
const payload = { application_uu_id: app.uu_id, service_uu_id: selectedItemServices.uu_id }
fetch(urlAppendersCreate, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
}).then((res) => {
if (res.ok) {
updatePaginationAppenders({
...paginationAppenders,
query: {
...paginationAppenders.query,
service_uu_id: selectedItemServices.uu_id
}
});
updatePaginationEvents({
...paginationEvents,
query: {
...paginationEvents.query,
service_uu_id: selectedItemServices.uu_id
}
});
}
})
}
const removeServiceEvent = async (app: ApplicationData) => {
if (!selectedItemServices?.uu_id) {
throw new Error("Service not selected");
}
const payload = { application_uu_id: app.uu_id, service_uu_id: selectedItemServices.uu_id }
fetch(urlAppendersDelete, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
}).then((res) => {
if (res.ok) {
updatePaginationAppenders({
...paginationAppenders,
query: {
...paginationAppenders.query,
service_uu_id: selectedItemServices.uu_id
}
});
updatePaginationEvents({
...paginationEvents,
query: {
...paginationEvents.query,
service_uu_id: selectedItemServices.uu_id
}
});
}
})
}
useEffect(() => {
setFieldDefinitionsServices(serviceViewFieldDefinitions); setValidationSchemaServices(ServiceSchema);
setFieldDefinitionsEvents(applicationViewFieldDefinitions); setValidationSchemaEvents(ApplicationSchema);
setFieldDefinitionsAppenders(applicationViewFieldDefinitions); setValidationSchemaAppenders(ApplicationSchema);
setLanguageTranslations({
mainTitle: translations[lang].mainTitle,
serviceSelectedTitle: translations[lang].serviceSelectedTitle,
serviceSelectedContent: translations[lang].serviceSelectedContent,
cancel: translations[lang].cancel,
});
}, [lang]);
useEffect(() => {
if (selectedItemServices && selectedItemServices?.uu_id) {
updatePaginationAppenders({
page: paginationAppenders.page,
size: paginationAppenders.size,
orderField: paginationAppenders.orderField,
orderType: paginationAppenders.orderType,
query: {
...paginationAppenders.query,
service_uu_id: selectedItemServices.uu_id
}
});
updatePaginationEvents({
page: paginationEvents.page,
size: paginationEvents.size,
orderField: paginationEvents.orderField,
orderType: paginationEvents.orderType,
query: {
...paginationEvents.query,
service_uu_id: selectedItemServices.uu_id
}
});
setSelectionBar(
selectedItemServices ?
`${selectedItemServices.uu_id} ${selectedItemServices?.service_name} ${translations[lang].serviceSelectedContent}` :
"No service is selected to be appended to applications"
);
}
}, [selectedItemServices]);
const handleQueryChangeServices = (key: string, value: string | null) => {
const newQuery = { ...paginationServices.query };
if (value === null) { delete newQuery[key] } else if (value.trim() === "") { delete newQuery[key] } else { newQuery[key] = value }
updatePaginationServices({ page: 1, query: newQuery })
};
const handleQueryChangeEvents = (key: string, value: string | null) => {
const newQuery = { ...paginationEvents.query };
if (value === null) { delete newQuery[key] } else if (value.trim() === "") { delete newQuery[key] } else { newQuery[key] = value }
if (selectedItemServices?.uu_id) {
newQuery.service_uu_id = selectedItemServices.uu_id;
}
updatePaginationEvents({ page: 1, query: newQuery });
};
const handleQueryChangeAppenders = (key: string, value: string | null) => {
const newQuery = { ...paginationAppenders.query };
if (value === null) { delete newQuery[key] } else if (value.trim() === "") { delete newQuery[key] } else { newQuery[key] = value }
if (selectedItemServices?.uu_id) {
newQuery.service_uu_id = selectedItemServices.uu_id;
}
updatePaginationAppenders({ page: 1, query: newQuery });
};
const handleServicesCardClick = (item: ServiceData) => { setSelectedItemServices(item) };
const handleServicesViewClick = (item: ServiceData) => { setSelectedItemServices(item); setMode("view"); };
const handleEventsCardClick = (item: ApplicationData) => { appendServiceEvent(item); };
const handleEventsViewClick = (item: ApplicationData) => { setSelectedItemEvents(item); setMode("view"); };
const handleAppendersCardClick = (item: ApplicationData) => { removeServiceEvent(item); };
const handleAppendersViewClick = (item: ApplicationData) => { setSelectedItemAppenders(item); setMode("view"); };
const cancelAllSelections = () => {
setMode("list");
setSelectedItemServices(null);
setSelectedItemEvents(null);
setSelectedItemAppenders(null);
};
const serviceListProps = {
lang,
loading: loadingServices,
error: errorServices,
data: dataServices,
pagination: paginationServices,
showFields: showFieldsServices,
gridCols: gridCols,
titleField: "service_name",
size: "lg" as CardSize,
handleQueryChange: handleQueryChangeServices,
updatePagination: updatePaginationServices,
handleCardClick: handleServicesCardClick,
handleViewClick: handleServicesViewClick
};
const eventsListProps = {
lang,
loading: loadingEvents,
error: errorEvents,
data: dataEvents,
pagination: paginationEvents,
showFields: showFieldsEvents,
gridCols: 1,
titleField: "description",
size: "lg" as CardSize,
handleQueryChange: handleQueryChangeEvents,
updatePagination: updatePaginationEvents,
handleCardClick: handleEventsCardClick,
handleViewClick: handleEventsViewClick
};
const appendersListProps = {
lang,
loading: loadingAppenders,
error: errorAppenders,
data: dataAppenders,
pagination: paginationAppenders,
showFields: showFieldsEvents,
gridCols: 1,
titleField: "description",
size: "lg" as CardSize,
handleQueryChange: handleQueryChangeAppenders,
updatePagination: updatePaginationAppenders,
handleCardClick: handleAppendersCardClick,
handleViewClick: handleAppendersViewClick
};
const serviceFormProps = {
initialData: selectedItemServices || undefined,
mode: mode,
refetch: refetchServices,
setMode: setMode,
setSelectedItem: setSelectedItemServices,
onCancel: cancelAllSelections,
lang: lang,
translations: translationsServices,
apiUrl: '/api/services',
formProps: {
fieldDefinitions: fieldDefinitionsServices,
validationSchema: validationSchemaServices,
fieldsByMode: serviceFieldsByMode
}
};
const eventsFormProps = {
initialData: selectedItemEvents || undefined,
mode: mode,
refetch: refetchEvents,
setMode: setMode,
setSelectedItem: setSelectedItemEvents,
onCancel: cancelAllSelections,
lang: lang,
translations: translationsApplications,
apiUrl: '/api/applications',
formProps: {
fieldDefinitions: fieldDefinitionsEvents,
validationSchema: validationSchemaEvents,
fieldsByMode: applicationFieldsByMode,
}
};
const appendersFormProps = {
initialData: selectedItemAppenders || undefined,
mode: mode,
refetch: refetchAppenders,
setMode: setMode,
setSelectedItem: setSelectedItemAppenders,
onCancel: cancelAllSelections,
lang: lang,
translations: translationsAppenders,
apiUrl: '/api/appenders/applications',
formProps: {
fieldDefinitions: fieldDefinitionsAppenders,
validationSchema: validationSchemaAppenders,
fieldsByMode: applicationFieldsByMode,
}
};
return (
<div className="container mx-auto p-4 overflow-y-auto" >
<div className="mb-4 flex justify-between items-center">
<h1 className="text-2xl font-bold">{languageTranslations.mainTitle}</h1>
<div className="flex space-x-4"><GridSelectionComponent gridCols={gridCols} setGridCols={setGridCols} /></div>
</div>
<Button onClick={cancelAllSelections}>{languageTranslations.cancel}</Button>
<Card className="my-5">
<CardHeader>{languageTranslations.serviceSelectedTitle}</CardHeader>
<CardContent>{selectionBar}</CardContent>
</Card>
{mode === "list" ? (
<div className="flex flex-col space-y-4">
{
!selectedItemServices ? <div className="w-full h-1/2"><ListComponentServices {...serviceListProps} /></div> :
<div className="w-full h-1/2">
<div className="flex flex-row space-x-4">
{
loadingEvents ? <Loader /> : <div className="flex-1"><ListComponentEvents {...eventsListProps} /></div>
}
{
loadingAppenders ? <Loader /> : <div className="flex-1"><ListComponentEvents {...appendersListProps} /></div>
}
</div>
</div>
}
</div>
) : (
<div className="flex flex-col space-y-4">
{selectedItemServices && <FormDisplay<ServiceData> {...serviceFormProps} />}
{selectedItemEvents && <FormDisplay<ApplicationData> {...eventsFormProps} />}
{selectedItemAppenders && <FormDisplay<ApplicationData> {...appendersFormProps} />}
</div>
)}
</div>
);
};
export default AppendersApplicationPage;

View File

@@ -1,8 +1,8 @@
import { z } from "zod";
import { flattenFieldDefinitions } from "@/eventRouters/schemas/zodSchemas";
export interface ApplicationData {
id?: number;
interface ApplicationData {
uu_id: string;
name: string;
application_code: string;
site_url: string;
@@ -15,7 +15,6 @@ export interface ApplicationData {
updated_at?: string;
}
// Validation error messages by language
const errorMessages = {
en: {
nameRequired: "Name is required",
@@ -31,7 +30,6 @@ const errorMessages = {
},
};
// Function to get schema with language-specific validation messages
const getApplicationBaseSchema = (lang: "en" | "tr" = "en") =>
z.object({
// Identification fields
@@ -58,10 +56,9 @@ const getApplicationBaseSchema = (lang: "en" | "tr" = "en") =>
updated_at: z.string().optional(),
});
// For backward compatibility
const ApplicationBaseSchema = getApplicationBaseSchema("en");
export const ApplicationBaseTranslationTr = {
const ApplicationBaseTranslationTr = {
uu_id: "UUID",
name: "Name",
application_code: "Application Code",
@@ -75,7 +72,7 @@ export const ApplicationBaseTranslationTr = {
updated_at: "Updated At",
};
export const ApplicationBaseTranslationEn = {
const ApplicationBaseTranslationEn = {
uu_id: "UUID",
name: "Name",
application_code: "Application Code",
@@ -89,7 +86,6 @@ export const ApplicationBaseTranslationEn = {
updated_at: "Updated At",
};
// Create schema for creating new applications with language support
const getCreateApplicationSchema = (lang: "en" | "tr" = "en") =>
getApplicationBaseSchema(lang).omit({
uu_id: true,
@@ -98,7 +94,6 @@ const getCreateApplicationSchema = (lang: "en" | "tr" = "en") =>
deleted: true,
});
// Update schema for updating existing applications with language support
const getUpdateApplicationSchema = (lang: "en" | "tr" = "en") =>
getApplicationBaseSchema(lang)
.omit({
@@ -110,34 +105,14 @@ const getUpdateApplicationSchema = (lang: "en" | "tr" = "en") =>
uu_id: true,
});
// For backward compatibility
const CreateApplicationSchema = getCreateApplicationSchema("en");
const UpdateApplicationSchema = getUpdateApplicationSchema("en");
// Schema for viewing an application (all fields)
const ViewApplicationSchema = ApplicationBaseSchema;
// Default schema (used for validation)
const ApplicationSchema = ApplicationBaseSchema;
// Export all schemas and schema generators
export {
ApplicationBaseSchema,
ApplicationSchema,
CreateApplicationSchema,
UpdateApplicationSchema,
ViewApplicationSchema,
getApplicationBaseSchema,
getCreateApplicationSchema,
getUpdateApplicationSchema,
};
type ApplicationFormData = z.infer<typeof ApplicationSchema>;
type ViewApplicationFormData = z.infer<typeof ViewApplicationSchema>;
export type ApplicationFormData = z.infer<typeof ApplicationSchema>;
export type CreateApplicationFormData = z.infer<typeof CreateApplicationSchema>;
export type UpdateApplicationFormData = z.infer<typeof UpdateApplicationSchema>;
export type ViewApplicationFormData = z.infer<typeof ViewApplicationSchema>;
const baseFieldDefinitions = {
const applicationBaseFieldDefinitions = {
// Identification fields
identificationInfo: {
title: "Identification Information",
order: 1,
@@ -171,6 +146,8 @@ const baseFieldDefinitions = {
},
},
},
// Application details
applicationDetails: {
title: "Application Details",
order: 2,
@@ -215,6 +192,8 @@ const baseFieldDefinitions = {
},
},
},
// Status fields
statusInfo: {
title: "Status Information",
order: 3,
@@ -241,6 +220,8 @@ const baseFieldDefinitions = {
},
},
},
// System fields
systemInfo: {
title: "System Information",
order: 4,
@@ -266,198 +247,101 @@ const baseFieldDefinitions = {
},
},
};
const applicationFlatFieldDefinitions = flattenFieldDefinitions(
applicationBaseFieldDefinitions
);
const flatFieldDefinitions = flattenFieldDefinitions(baseFieldDefinitions);
export const createFieldDefinitions = {
name: {
...flatFieldDefinitions.name,
readOnly: false,
required: true,
defaultValue: "",
},
application_code: {
...flatFieldDefinitions.application_code,
readOnly: false,
required: true,
defaultValue: "",
},
site_url: {
...flatFieldDefinitions.site_url,
readOnly: false,
required: true,
defaultValue: "",
},
application_type: {
...flatFieldDefinitions.application_type,
readOnly: false,
required: true,
defaultValue: "",
},
application_for: {
...flatFieldDefinitions.application_for,
readOnly: false,
required: false,
defaultValue: "EMP",
},
description: {
...flatFieldDefinitions.description,
readOnly: false,
required: false,
defaultValue: "",
},
active: {
...flatFieldDefinitions.active,
readOnly: false,
required: false,
defaultValue: true,
},
};
export const updateFieldDefinitions = {
const applicationViewFieldDefinitions = {
uu_id: {
...flatFieldDefinitions.uu_id,
readOnly: true,
required: false,
defaultValue: "",
},
name: {
...flatFieldDefinitions.name,
readOnly: false,
required: true,
defaultValue: "",
},
application_code: {
...flatFieldDefinitions.application_code,
readOnly: false,
required: true,
defaultValue: "",
},
site_url: {
...flatFieldDefinitions.site_url,
readOnly: false,
required: true,
defaultValue: "",
},
application_type: {
...flatFieldDefinitions.application_type,
readOnly: false,
required: true,
defaultValue: "",
},
application_for: {
...flatFieldDefinitions.application_for,
readOnly: false,
required: false,
defaultValue: "",
},
description: {
...flatFieldDefinitions.description,
readOnly: false,
required: false,
defaultValue: "",
},
active: {
...flatFieldDefinitions.active,
readOnly: false,
required: false,
defaultValue: true,
},
};
export const viewFieldDefinitions = {
uu_id: {
...flatFieldDefinitions.uu_id,
...applicationFlatFieldDefinitions.uu_id,
readOnly: true,
required: false,
defaultValue: 0,
},
name: {
...flatFieldDefinitions.name,
...applicationFlatFieldDefinitions.name,
readOnly: true,
required: false,
defaultValue: "",
},
application_code: {
...flatFieldDefinitions.application_code,
...applicationFlatFieldDefinitions.application_code,
readOnly: true,
required: false,
defaultValue: "",
},
site_url: {
...flatFieldDefinitions.site_url,
...applicationFlatFieldDefinitions.site_url,
readOnly: true,
required: false,
defaultValue: "",
},
application_type: {
...flatFieldDefinitions.application_type,
...applicationFlatFieldDefinitions.application_type,
readOnly: true,
required: false,
defaultValue: "",
},
application_for: {
...flatFieldDefinitions.application_for,
...applicationFlatFieldDefinitions.application_for,
readOnly: true,
required: false,
defaultValue: "",
},
description: {
...flatFieldDefinitions.description,
...applicationFlatFieldDefinitions.description,
readOnly: true,
required: false,
defaultValue: "",
},
active: {
...flatFieldDefinitions.active,
...applicationFlatFieldDefinitions.active,
readOnly: true,
required: false,
defaultValue: true,
},
deleted: {
...flatFieldDefinitions.deleted,
...applicationFlatFieldDefinitions.deleted,
readOnly: true,
required: false,
defaultValue: false,
},
created_at: {
...flatFieldDefinitions.created_at,
...applicationFlatFieldDefinitions.created_at,
readOnly: true,
required: false,
defaultValue: "",
},
updated_at: {
...flatFieldDefinitions.updated_at,
...applicationFlatFieldDefinitions.updated_at,
readOnly: true,
required: false,
defaultValue: "",
},
};
export const fieldDefinitions = {
...baseFieldDefinitions,
getDefinitionsByMode: (mode: "create" | "update" | "view") => {
const applicationFieldDefinitions = {
...applicationBaseFieldDefinitions,
getDefinitionsByMode: (mode: "view") => {
switch (mode) {
case "create":
return createFieldDefinitions;
case "update":
return updateFieldDefinitions;
case "view":
return viewFieldDefinitions;
return applicationViewFieldDefinitions;
default:
return baseFieldDefinitions;
return applicationFieldDefinitions;
}
},
};
// Fields to show based on mode - dynamically generated from field definitions
export const fieldsByMode = {
create: Object.keys(createFieldDefinitions),
update: Object.keys(updateFieldDefinitions),
view: Object.keys(viewFieldDefinitions),
const applicationFieldsByMode = {
view: Object.keys(applicationViewFieldDefinitions),
};
export type FieldDefinitionsType =
| typeof createFieldDefinitions
| typeof updateFieldDefinitions
| typeof viewFieldDefinitions;
type ApplicationFieldDefinitionsType = typeof applicationViewFieldDefinitions;
export type { ApplicationData, ApplicationFieldDefinitionsType };
export {
ApplicationSchema,
applicationFlatFieldDefinitions,
ApplicationBaseTranslationEn,
ApplicationBaseTranslationTr,
applicationFieldsByMode,
applicationViewFieldDefinitions,
};

View File

@@ -1,8 +0,0 @@
import { PageProps } from "@/validations/translations/translation";
import React from "react";
const EventAppendPage: React.FC<PageProps> = () => {
return <div>EventAppendPage</div>;
};
export default EventAppendPage;

View File

@@ -0,0 +1,217 @@
import React from 'react';
import { translations } from './language';
import { Filter } from 'lucide-react';
import { Card, CardContent } from '@/components/ui/card';
import { TextQueryModifier } from '@/components/common/QueryModifiers/TextQueryModifier';
import { PaginationToolsComponent } from '@/components/common/PaginationModifiers/PaginationToolsComponent';
import { CardDisplay } from '@/components/common/CardDisplay/CardDisplay';
import { ListComponentEventsProps, ListComponentServicesProps } from './type';
const ListComponentServices: React.FC<ListComponentServicesProps> = ({
lang,
loading,
error,
data,
pagination,
showFields,
gridCols,
titleField,
size,
handleQueryChange,
updatePagination,
handleCardClick,
handleViewClick,
}) => {
const fieldKey = "service_name";
return (
<>
{/* Search Filters */}
<Card>
<CardContent className="pt-6">
<div className="flex flex-col md:flex-row">
{/* Filters on the right */}
<div className={`w-full flex flex-col space-y-4`}>
<div className="font-medium text-sm mb-2 flex justify-between items-center">
<div className="flex items-center">
<Filter className="mr-2 h-4 w-4" />{translations[lang].filterSelection}
</div>
</div>
{/* Search input */}
<TextQueryModifier
fieldKey={fieldKey}
value={pagination.query[`${fieldKey}__ilike`] ? pagination.query[`${fieldKey}__ilike`].replace(/%/g, "") : ""}
label={translations[lang].search}
onQueryChange={handleQueryChange}
translations={translations}
lang={lang}
/>
</div>
</div>
</CardContent>
</Card>
{/* Pagination Tools Component */}
<Card className="my-4">
<CardContent className="pt-6">
<PaginationToolsComponent
pagination={pagination}
updatePagination={updatePagination}
loading={loading}
lang={lang}
translations={translations}
/>
</CardContent>
</Card>
{/* Card Display Component */}
<div className="mt-6">
<CardDisplay
showFields={showFields}
data={data}
lang={lang}
translations={translations}
error={error}
loading={loading}
titleField={titleField}
onCardClick={handleCardClick}
gridCols={gridCols}
size={size}
showViewIcon={true}
onViewClick={handleViewClick}
/>
</div>
</>
);
};
const ListComponentEvents: React.FC<ListComponentEventsProps> = ({
lang,
loading,
error,
data,
pagination,
showFields,
gridCols,
size,
handleQueryChange,
updatePagination,
handleCardClick,
handleViewClick,
}) => {
const fieldKey = "description";
return (
<>
{/* Search Filters */}
<Card>
<CardContent className="pt-6">
<div className="flex flex-col md:flex-row">
{/* Filters on the right */}
<div className={`w-full flex flex-col space-y-4`}>
<div className="font-medium text-sm mb-2 flex justify-between items-center">
<div className="flex items-center">
<Filter className="mr-2 h-4 w-4" />{translations[lang].filterSelection}
</div>
</div>
{/* Search input */}
<TextQueryModifier
fieldKey={fieldKey}
value={pagination.query[`${fieldKey}__ilike`] ? pagination.query[`${fieldKey}__ilike`].replace(/%/g, "") : ""}
label={translations[lang].search}
onQueryChange={handleQueryChange}
translations={translations}
lang={lang}
/>
</div>
</div>
</CardContent>
</Card>
{/* Pagination Tools Component */}
<Card className="my-4">
<CardContent className="pt-6">
<PaginationToolsComponent
pagination={pagination}
updatePagination={updatePagination}
loading={loading}
lang={lang}
translations={translations}
/>
</CardContent>
</Card>
{/* Card Display Component */}
<div className="mt-6">
<CardDisplay
showFields={showFields}
data={data}
lang={lang}
translations={translations}
error={error}
loading={loading}
titleField="name"
onCardClick={handleCardClick}
gridCols={gridCols}
showViewIcon={true}
onViewClick={handleViewClick}
size={size}
/>
</div>
</>
);
};
const ListComponentAppenders: React.FC<ListComponentEventsProps> = ({
lang,
loading,
error,
data,
pagination,
showFields,
gridCols,
size,
updatePagination,
handleCardClick,
handleViewClick,
}) => {
return (
<>
{/* Pagination Tools Component */}
<Card className="my-4">
<CardContent className="pt-6">
<PaginationToolsComponent
pagination={pagination}
updatePagination={updatePagination}
loading={loading}
lang={lang}
translations={translations}
/>
</CardContent>
</Card>
{/* Card Display Component */}
<div className="mt-6">
<CardDisplay
showFields={showFields}
data={data}
lang={lang}
translations={translations}
error={error}
loading={loading}
titleField="name"
onCardClick={handleCardClick}
gridCols={gridCols}
showViewIcon={true}
onViewClick={handleViewClick}
size={size}
/>
</div>
</>
);
};
export {
ListComponentEvents,
ListComponentServices,
ListComponentAppenders,
};

View File

@@ -1,7 +1,6 @@
"use client";
import React, { useState, useEffect } from "react";
import { z } from "zod";
import {
ServiceData,
serviceViewFieldDefinitions,
@@ -18,7 +17,6 @@ import {
} from "./schemaList/events";
import { ListComponentEvents, ListComponentServices } from "./listComponent";
import { translations, translationsServices, translationsAppenders, translationsEvents } from "./language";
import { PageProps } from "@/validations/translations/translation";
import { FormModeView, FormMode } from "@/components/common/FormDisplay/types";
import { FormDisplay } from "@/components/common/FormDisplay/FormDisplay";
@@ -28,8 +26,17 @@ import { Language } from "@/components/common/schemas";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { CardSize } from "@/components/common/CardDisplay/schema";
import Loader from "@/components/common/Loader/loader";
const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language }) => {
const AppendersEventsPage: React.FC<PageProps> = ({ lang }: { lang: Language }) => {
const urlServices = '/api/services/list';
const urlEvents = '/api/events/list';
const urlAppenders = '/api/appenders/events/list';
const urlAppendersCreate = '/api/appenders/events/create';
const urlAppendersDelete = '/api/appenders/events/delete';
const showFieldsServices = ["service_name", "service_code", "related_responsibility"];
const showFieldsEvents = ["description", "marketing_layer", "cost"];
const {
data: dataServices,
@@ -38,7 +45,7 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
error: errorServices,
updatePagination: updatePaginationServices,
refetch: refetchServices
} = useApiData<ServiceData>('/api/services');
} = useApiData<ServiceData>(urlServices);
const {
data: dataEvents,
pagination: paginationEvents,
@@ -46,7 +53,7 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
error: errorEvents,
updatePagination: updatePaginationEvents,
refetch: refetchEvents
} = useApiData<EventData>('/api/events');
} = useApiData<EventData>(urlEvents);
const {
data: dataAppenders,
pagination: paginationAppenders,
@@ -54,7 +61,7 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
error: errorAppenders,
updatePagination: updatePaginationAppenders,
refetch: refetchAppenders
} = useApiData<EventData>('/api/appenders');
} = useApiData<EventData>(urlAppenders);
const [mode, setMode] = useState<FormModeView | FormMode>("list");
const [gridCols, setGridCols] = useState<GridSize>(3);
@@ -70,14 +77,33 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
const [validationSchemaServices, setValidationSchemaServices] = useState<z.ZodSchema | null>(null);
const [validationSchemaEvents, setValidationSchemaEvents] = useState<z.ZodSchema | null>(null);
const [validationSchemaAppenders, setValidationSchemaAppenders] = useState<z.ZodSchema | null>(null);
const [selectionBar, setSelectionBar] = useState<string>("");
const [languageTranslations, setLanguageTranslations] = useState({
mainTitle: translations[lang].mainTitle,
serviceSelectedTitle: translations[lang].serviceSelectedTitle,
serviceSelectedContent: translations[lang].serviceSelectedContent,
cancel: translations[lang].cancel,
});
const showFieldsServices = ["service_name", "service_code", "related_responsibility"];
const showFieldsEvents = ["description", "marketing_layer", "cost"];
const handleServicesCardClick = (item: ServiceData) => { setSelectedItemServices(item) };
const handleServicesViewClick = (item: ServiceData) => { setSelectedItemServices(item); setMode("view"); };
const handleEventsCardClick = (item: EventData) => { appendServiceEvent(item); };
const handleEventsViewClick = (item: EventData) => { setSelectedItemEvents(item); setMode("view"); };
const handleAppendersCardClick = (item: EventData) => { removeServiceEvent(item); };
const handleAppendersViewClick = (item: EventData) => { setSelectedItemAppenders(item); setMode("view"); };
useEffect(() => {
setFieldDefinitionsServices(serviceViewFieldDefinitions); setValidationSchemaServices(ServiceSchema);
setFieldDefinitionsEvents(eventFlatFieldDefinitions); setValidationSchemaEvents(EventSchema);
setFieldDefinitionsAppenders(eventFlatFieldDefinitions); setValidationSchemaAppenders(EventSchema);
setLanguageTranslations({
mainTitle: translations[lang].mainTitle,
serviceSelectedTitle: translations[lang].serviceSelectedTitle,
serviceSelectedContent: translations[lang].serviceSelectedContent,
cancel: translations[lang].cancel,
});
}, [lang]);
useEffect(() => {
@@ -92,7 +118,6 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
service_uu_id: selectedItemServices.uu_id
}
});
updatePaginationEvents({
page: paginationEvents.page,
size: paginationEvents.size,
@@ -103,7 +128,13 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
service_uu_id: selectedItemServices.uu_id
}
});
setSelectionBar(
selectedItemServices ?
`${selectedItemServices.uu_id} ${selectedItemServices?.service_name} ${translations[lang].serviceSelectedContent}` :
"No service is selected to be appended to events"
);
}
}, [selectedItemServices]);
const handleQueryChangeServices = (key: string, value: string | null) => {
@@ -115,7 +146,6 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
const handleQueryChangeEvents = (key: string, value: string | null) => {
const newQuery = { ...paginationEvents.query };
if (value === null) { delete newQuery[key] } else if (value.trim() === "") { delete newQuery[key] } else { newQuery[key] = value }
if (selectedItemServices?.uu_id) {
newQuery.service_uu_id = selectedItemServices.uu_id;
}
@@ -136,7 +166,7 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
throw new Error("Service not selected");
}
const payload = { event_uu_id: event.uu_id, service_uu_id: selectedItemServices.uu_id }
fetch('/api/appenders/create', {
fetch(urlAppendersCreate, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
@@ -165,7 +195,7 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
throw new Error("Service not selected");
}
const payload = { event_uu_id: event.uu_id, service_uu_id: selectedItemServices.uu_id }
fetch('/api/appenders/delete', {
fetch(urlAppendersDelete, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
@@ -189,15 +219,6 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
})
}
const handleServicesCardClick = (item: ServiceData) => { setSelectedItemServices(item); setMode("list"); };
const handleServicesViewClick = (item: ServiceData) => { setSelectedItemServices(item); setMode("view"); };
const handleEventsCardClick = (item: EventData) => { appendServiceEvent(item); };
const handleEventsViewClick = (item: EventData) => { setSelectedItemEvents(item); setMode("view"); };
const handleAppendersCardClick = (item: EventData) => { removeServiceEvent(item); };
const handleAppendersViewClick = (item: EventData) => { setSelectedItemAppenders(item); setMode("view"); };
const cancelAllSelections = () => {
setMode("list");
setSelectedItemServices(null);
@@ -307,22 +328,22 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
return (
<div className="container mx-auto p-4 overflow-y-auto" >
<div className="mb-4 flex justify-between items-center">
<h1 className="text-2xl font-bold">{translations[lang].mainTitle}</h1>
<h1 className="text-2xl font-bold">{languageTranslations.mainTitle}</h1>
<div className="flex space-x-4"><GridSelectionComponent gridCols={gridCols} setGridCols={setGridCols} /></div>
</div>
<Button onClick={cancelAllSelections}>{languageTranslations.cancel}</Button>
<Card className="my-5">
<CardHeader>{languageTranslations.serviceSelectedTitle}</CardHeader>
<CardContent>{selectionBar}</CardContent>
</Card>
{mode === "list" ? (
<div className="flex flex-col space-y-4">
{
!selectedItemServices ? <div className="w-full h-1/2"><ListComponentServices {...serviceListProps} /></div> :
<div className="w-full h-1/2">
<Button onClick={cancelAllSelections}>{translations[lang].cancel}</Button>
<Card className="my-5">
<CardHeader>{translations[lang].serviceSelectedTitle}</CardHeader>
<CardContent>{selectedItemServices.uu_id}{" "}{selectedItemServices?.service_name}{" "}{translations[lang].serviceSelectedContent}</CardContent>
</Card>
<div className="flex flex-row space-x-4">
<div className="flex-1"><ListComponentEvents {...eventsListProps} /></div>
<div className="flex-1"><ListComponentEvents {...appendersListProps} /></div>
{loadingEvents ? <Loader /> : <div className="flex-1"><ListComponentEvents {...eventsListProps} /></div>}
{loadingAppenders ? <Loader /> : <div className="flex-1"><ListComponentEvents {...appendersListProps} /></div>}
</div>
</div>
}
@@ -338,4 +359,4 @@ const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language })
);
};
export default AppendersServicePage;
export default AppendersEventsPage;

View File

@@ -0,0 +1,295 @@
import { z } from "zod";
import { flattenFieldDefinitions } from "@/eventRouters/schemas/zodSchemas";
interface ServiceData {
uu_id: string;
module_uu_id: string;
service_name: string;
service_description?: string;
service_code: string;
related_responsibility?: string;
is_confirmed: boolean;
active: boolean;
deleted?: boolean;
created_at?: string;
updated_at?: string;
}
const errorMessages = {
en: {
moduleUuIdRequired: "Module UUID is required",
serviceNameRequired: "Service name is required",
serviceCodeRequired: "Service code is required",
},
tr: {
moduleUuIdRequired: "Modül UUID'si gereklidir",
serviceNameRequired: "Servis adı gereklidir",
serviceCodeRequired: "Servis kodu gereklidir",
},
};
const getServiceBaseSchema = (lang: "en" | "tr" = "en") =>
z.object({
uu_id: z.string().optional(),
module_uu_id: z.string().min(1, errorMessages[lang].moduleUuIdRequired),
service_name: z.string().min(1, errorMessages[lang].serviceNameRequired),
service_description: z.string().optional(),
service_code: z.string().min(1, errorMessages[lang].serviceCodeRequired),
related_responsibility: z.string().optional(),
is_confirmed: z.boolean().default(false),
active: z.boolean().default(true),
deleted: z.boolean().default(false),
created_at: z.string().optional(),
updated_at: z.string().optional(),
});
const ServiceBaseSchema = getServiceBaseSchema("en");
const ServiceBaseTranslationTr = {
uu_id: "UUID",
module_uu_id: "Modül UUID'si",
service_name: "Servis Adı",
service_description: "Servis Açıklaması",
service_code: "Servis Kodu",
related_responsibility: "İlgili Sorumluluk",
is_confirmed: "Onaylandı",
active: "Active",
deleted: "Deleted",
created_at: "Created At",
updated_at: "Updated At",
};
const ServiceBaseTranslationEn = {
uu_id: "UUID",
module_uu_id: "Module UUID",
service_name: "Service Name",
service_description: "Service Description",
service_code: "Service Code",
related_responsibility: "Related Responsibility",
is_confirmed: "Confirmed",
active: "Active",
deleted: "Deleted",
created_at: "Created At",
updated_at: "Updated At",
};
const ViewServiceSchema = ServiceBaseSchema;
const ServiceSchema = ServiceBaseSchema;
const serviceBaseFieldDefinitions = {
identificationInfo: {
title: "Service Information",
order: 1,
fields: {
uu_id: {
type: "text",
label: {
tr: ServiceBaseTranslationTr.uu_id,
en: ServiceBaseTranslationEn.uu_id,
},
readOnly: true,
required: false,
},
module_uu_id: {
type: "text",
label: {
tr: ServiceBaseTranslationTr.module_uu_id,
en: ServiceBaseTranslationEn.module_uu_id,
},
readOnly: false,
required: true,
},
service_name: {
type: "text",
label: {
tr: ServiceBaseTranslationTr.service_name,
en: ServiceBaseTranslationEn.service_name,
},
readOnly: false,
required: true,
},
service_description: {
type: "text",
label: {
tr: ServiceBaseTranslationTr.service_description,
en: ServiceBaseTranslationEn.service_description,
},
readOnly: false,
required: true,
},
service_code: {
type: "text",
label: {
tr: ServiceBaseTranslationTr.service_code,
en: ServiceBaseTranslationEn.service_code,
},
readOnly: false,
required: true,
},
related_responsibility: {
type: "text",
label: {
tr: ServiceBaseTranslationTr.related_responsibility,
en: ServiceBaseTranslationEn.related_responsibility,
},
readOnly: false,
required: false,
},
},
},
statusInfo: {
title: "Status Information",
order: 3,
fields: {
active: {
type: "checkbox",
label: {
tr: ServiceBaseTranslationTr.active,
en: ServiceBaseTranslationEn.active,
},
readOnly: false,
required: false,
defaultValue: true,
},
deleted: {
type: "checkbox",
label: {
tr: ServiceBaseTranslationTr.deleted,
en: ServiceBaseTranslationEn.deleted,
},
readOnly: true,
required: false,
defaultValue: false,
},
is_confirmed: {
type: "checkbox",
label: {
tr: ServiceBaseTranslationTr.is_confirmed,
en: ServiceBaseTranslationEn.is_confirmed,
},
readOnly: false,
required: true,
},
},
},
systemInfo: {
title: "System Information",
order: 4,
fields: {
created_at: {
type: "date",
label: {
tr: ServiceBaseTranslationTr.created_at,
en: ServiceBaseTranslationEn.created_at,
},
readOnly: true,
required: false,
},
updated_at: {
type: "date",
label: {
tr: ServiceBaseTranslationTr.updated_at,
en: ServiceBaseTranslationEn.updated_at,
},
readOnly: true,
required: false,
},
},
},
};
const serviceFlatFieldDefinitions = flattenFieldDefinitions(
serviceBaseFieldDefinitions
);
const serviceViewFieldDefinitions = {
uu_id: {
...serviceFlatFieldDefinitions.uu_id,
readOnly: true,
required: false,
defaultValue: 0,
},
module_uu_id: {
...serviceFlatFieldDefinitions.module_uu_id,
readOnly: true,
required: false,
defaultValue: "",
},
service_name: {
...serviceFlatFieldDefinitions.service_name,
readOnly: true,
required: false,
defaultValue: "",
},
service_description: {
...serviceFlatFieldDefinitions.service_description,
readOnly: true,
required: false,
defaultValue: "",
},
service_code: {
...serviceFlatFieldDefinitions.service_code,
readOnly: true,
required: false,
defaultValue: "",
},
related_responsibility: {
...serviceFlatFieldDefinitions.related_responsibility,
readOnly: true,
required: false,
defaultValue: "",
},
active: {
...serviceFlatFieldDefinitions.active,
readOnly: true,
required: false,
defaultValue: true,
},
is_confirmed: {
...serviceFlatFieldDefinitions.is_confirmed,
readOnly: true,
required: false,
defaultValue: true,
},
deleted: {
...serviceFlatFieldDefinitions.deleted,
readOnly: true,
required: false,
defaultValue: false,
},
created_at: {
...serviceFlatFieldDefinitions.created_at,
readOnly: true,
required: false,
defaultValue: "",
},
updated_at: {
...serviceFlatFieldDefinitions.updated_at,
readOnly: true,
required: false,
defaultValue: "",
},
};
const serviceFieldDefinitions = {
...serviceBaseFieldDefinitions,
getDefinitionsByMode: (mode: "view") => {
switch (mode) {
case "view":
return serviceViewFieldDefinitions;
default:
return serviceBaseFieldDefinitions;
}
},
};
const serviceFieldsByMode = {
view: Object.keys(serviceViewFieldDefinitions),
};
type ServiceFormData = z.infer<typeof ServiceSchema>;
type ServiceViewFormData = z.infer<typeof ViewServiceSchema>;
type ServiceFieldDefinitionsType = typeof serviceViewFieldDefinitions;
export type { ServiceData, ServiceFieldDefinitionsType };
export {
ServiceSchema,
serviceViewFieldDefinitions,
ServiceBaseTranslationEn,
ServiceBaseTranslationTr,
serviceFieldsByMode,
};

View File

@@ -0,0 +1,37 @@
import { Language } from "@/components/common/schemas";
import { GridSize } from "@/components/common/HeaderSelections/GridSelectionComponent";
import { CardSize } from "@/components/common/CardDisplay/schema";
import * as schemaServices from "./schemaList/services";
import * as schemaEvents from "./schemaList/events";
export interface ListComponentServicesProps {
lang: Language;
loading: boolean;
error: any;
data: schemaServices.ServiceData[];
pagination: any;
showFields: string[];
gridCols: GridSize | number;
titleField: string;
size: CardSize;
handleQueryChange: (key: string, value: string | null) => void;
updatePagination: (pagination: any) => void;
handleCardClick: (item: schemaServices.ServiceData) => void;
handleViewClick: (item: schemaServices.ServiceData) => void;
}
export interface ListComponentEventsProps {
lang: Language;
loading: boolean;
error: any;
data: schemaEvents.EventData[];
pagination: any;
showFields: string[];
gridCols: GridSize | number;
titleField: string;
size: CardSize;
handleQueryChange: (key: string, value: string | null) => void;
updatePagination: (pagination: any) => void;
handleCardClick: (item: schemaEvents.EventData) => void;
handleViewClick: (item: schemaEvents.EventData) => void;
}

View File

@@ -22,7 +22,7 @@ import { Language } from "@/components/common/schemas";
const ApplicationPage: React.FC<PageProps> = ({ lang }: { lang: Language }) => {
const { data, pagination, loading, error, updatePagination, refetch } = useApiData<schema.ApplicationData>('/api/applications');
const { data, pagination, loading, error, updatePagination, refetch } = useApiData<schema.ApplicationData>('/api/applications/pages');
const [mode, setMode] = useState<FormMode>("list");
const [selectedItem, setSelectedItem] = useState<schema.ApplicationData | null>(null);

View File

@@ -2,7 +2,7 @@ import { z } from "zod";
import { flattenFieldDefinitions } from "@/eventRouters/schemas/zodSchemas";
export interface ApplicationData {
id?: number;
uu_id: string;
name: string;
application_code: string;
site_url: string;

View File

@@ -1,13 +1,13 @@
import DashboardPage from "./dashboard/page";
import ApplicationPage from "./application/page";
import EventAppendPage from "./appenderEvent/page";
import ServiceAppendPage from "./appendersService/page";
import AppendersEventsPage from "./appenderApplication/page";
import AppendersServicePage from "./appendersEvents/page";
const menuPages = {
"/dashboard": DashboardPage,
"/application": ApplicationPage,
"/append/event": EventAppendPage,
"/append/service": ServiceAppendPage
"/append/event": AppendersEventsPage,
"/append/service": AppendersServicePage
};
export default menuPages;