updated management service bind
This commit is contained in:
parent
c6b1a2b1e8
commit
ac8c3fe1c3
|
|
@ -47,7 +47,7 @@ export function CardDisplay<T>({
|
|||
{(translations[lang] || {}).noData || "No data found"}
|
||||
</div>
|
||||
) : (
|
||||
data.map((item, index) => (
|
||||
data.map((item: T, index: number) => (
|
||||
<CardItem
|
||||
key={index}
|
||||
item={item}
|
||||
|
|
|
|||
|
|
@ -19,16 +19,12 @@ export function FormDisplay<T>({
|
|||
}: FormDisplayProps<T>) {
|
||||
const [enhancedFormProps, setEnhancedFormProps] = useState(formProps);
|
||||
|
||||
// Update form props when language or mode changes
|
||||
useEffect(() => {
|
||||
const updateFormProps = async () => {
|
||||
try {
|
||||
// Check if schemaPath is provided in formProps
|
||||
if (formProps.schemaPath) {
|
||||
// Dynamic import of the schema module
|
||||
const schemaModule = await import(formProps.schemaPath);
|
||||
|
||||
// Get the appropriate field definitions based on mode
|
||||
let fieldDefs;
|
||||
if (schemaModule.fieldDefinitions?.getDefinitionsByMode) {
|
||||
fieldDefs = schemaModule.fieldDefinitions.getDefinitionsByMode(mode);
|
||||
|
|
@ -40,13 +36,10 @@ export function FormDisplay<T>({
|
|||
fieldDefs = schemaModule.viewFieldDefinitions;
|
||||
}
|
||||
|
||||
// Get the appropriate validation schema based on mode and language
|
||||
let validationSchema;
|
||||
if (mode === "create" && schemaModule.getCreateApplicationSchema) {
|
||||
// Use language-aware schema factory function
|
||||
validationSchema = schemaModule.getCreateApplicationSchema(lang as "en" | "tr");
|
||||
} else if (mode === "update" && schemaModule.getUpdateApplicationSchema) {
|
||||
// Use language-aware schema factory function
|
||||
validationSchema = schemaModule.getUpdateApplicationSchema(lang as "en" | "tr");
|
||||
} else if (mode === "view" && schemaModule.ViewApplicationSchema) {
|
||||
validationSchema = schemaModule.ViewApplicationSchema;
|
||||
|
|
@ -54,23 +47,17 @@ export function FormDisplay<T>({
|
|||
validationSchema = schemaModule.ApplicationSchema;
|
||||
}
|
||||
|
||||
// Get the grouped field definitions structure if available
|
||||
const groupedFieldDefs = schemaModule.baseFieldDefinitions || {};
|
||||
|
||||
// Update form props with schema information and current language
|
||||
setEnhancedFormProps({
|
||||
...formProps,
|
||||
fieldDefinitions: fieldDefs || {},
|
||||
validationSchema,
|
||||
fieldsByMode: schemaModule.fieldsByMode || {},
|
||||
groupedFieldDefinitions: groupedFieldDefs,
|
||||
// Add current language to force child components to recognize changes
|
||||
currentLang: lang,
|
||||
// Add schema path for dynamic imports in child components
|
||||
schemaPath: formProps.schemaPath
|
||||
});
|
||||
} else {
|
||||
// If no schema path, just update with current language
|
||||
setEnhancedFormProps({
|
||||
...formProps,
|
||||
currentLang: lang
|
||||
|
|
@ -78,7 +65,6 @@ export function FormDisplay<T>({
|
|||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading schema definitions:", error);
|
||||
// Even on error, update the language
|
||||
setEnhancedFormProps({
|
||||
...formProps,
|
||||
currentLang: lang
|
||||
|
|
@ -87,17 +73,13 @@ export function FormDisplay<T>({
|
|||
};
|
||||
|
||||
updateFormProps();
|
||||
}, [formProps, mode, lang]); // Lang dependency ensures re-fetch when language changes
|
||||
}, [formProps, mode, lang]);
|
||||
|
||||
// Debug the props received by FormDisplay
|
||||
// FormDisplay component renders different form modes based on the mode prop
|
||||
|
||||
// Render the appropriate component based on the mode
|
||||
switch (mode) {
|
||||
case "create":
|
||||
return (
|
||||
<CreateComponent<T>
|
||||
key={`create-${lang}`} // Add key with lang to force re-render on language change
|
||||
key={`create-${lang}`}
|
||||
refetch={refetch}
|
||||
setMode={setMode}
|
||||
setSelectedItem={setSelectedItem}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"use client";
|
||||
|
||||
// Import field definitions type
|
||||
export interface FieldDefinition {
|
||||
type: string;
|
||||
group: string;
|
||||
|
|
@ -12,13 +11,13 @@ export interface FieldDefinition {
|
|||
name?: string;
|
||||
}
|
||||
|
||||
// Define the FormMode type to ensure consistency
|
||||
export type FormMode = "list" | "create" | "update" | "view";
|
||||
export type FormModeView = "list" | "view";
|
||||
|
||||
export interface BaseFormProps<T> {
|
||||
initialData?: T;
|
||||
refetch?: () => void;
|
||||
setMode: React.Dispatch<React.SetStateAction<FormMode>>;
|
||||
setMode: React.Dispatch<React.SetStateAction<FormMode | FormModeView>>;
|
||||
setSelectedItem: React.Dispatch<React.SetStateAction<T | null>>;
|
||||
onCancel: () => void;
|
||||
lang: string;
|
||||
|
|
@ -30,19 +29,19 @@ export interface BaseFormProps<T> {
|
|||
export interface CreateComponentProps<T> extends BaseFormProps<T> {}
|
||||
|
||||
export interface UpdateComponentProps<T> extends BaseFormProps<T> {
|
||||
initialData: T; // Required for update
|
||||
initialData: T;
|
||||
apiUrl: string;
|
||||
}
|
||||
|
||||
export interface ViewComponentProps<T> extends BaseFormProps<T> {
|
||||
initialData: T; // Required for view
|
||||
initialData: T;
|
||||
}
|
||||
|
||||
export interface FormDisplayProps<T> {
|
||||
mode: FormMode;
|
||||
mode: FormMode | FormModeView;
|
||||
initialData?: T;
|
||||
refetch?: () => void;
|
||||
setMode: React.Dispatch<React.SetStateAction<FormMode>>;
|
||||
setMode: React.Dispatch<React.SetStateAction<FormModeView | FormMode>>;
|
||||
setSelectedItem: React.Dispatch<React.SetStateAction<T | null>>;
|
||||
onCancel: () => void;
|
||||
lang: string;
|
||||
|
|
|
|||
|
|
@ -10,26 +10,21 @@ export const TextQueryModifier: React.FC<TextQueryModifierProps> = ({
|
|||
value,
|
||||
label,
|
||||
placeholder,
|
||||
onQueryChange,
|
||||
translations,
|
||||
lang,
|
||||
onQueryChange,
|
||||
}) => {
|
||||
const t = translations[lang] || {};
|
||||
|
||||
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const newValue = e.target.value;
|
||||
onQueryChange(fieldKey, newValue);
|
||||
const newValue = e.target.value; onQueryChange(fieldKey, newValue);
|
||||
}, [fieldKey, onQueryChange]);
|
||||
|
||||
const handleClear = useCallback(() => {
|
||||
// Clear both the regular field and the ilike filter
|
||||
onQueryChange(fieldKey, null);
|
||||
onQueryChange(`${fieldKey}__ilike`, null);
|
||||
onQueryChange(fieldKey, null); onQueryChange(`${fieldKey}__ilike`, null);
|
||||
}, [fieldKey, onQueryChange]);
|
||||
|
||||
const handleKeyUp = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter') {
|
||||
// Apply the search immediately on Enter
|
||||
const formattedValue = value.trim() ? `%${value.trim()}%` : null;
|
||||
onQueryChange(`${fieldKey}__ilike`, formattedValue);
|
||||
}
|
||||
|
|
@ -42,9 +37,7 @@ export const TextQueryModifier: React.FC<TextQueryModifierProps> = ({
|
|||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<label className="block text-xs font-medium mb-1">
|
||||
{label || t[fieldKey] || fieldKey}
|
||||
</label>
|
||||
<label className="block text-xs font-medium mb-1">{label || t[fieldKey] || fieldKey}</label>
|
||||
<div className="relative w-full flex">
|
||||
<div className="relative w-full">
|
||||
<Input
|
||||
|
|
@ -61,19 +54,15 @@ export const TextQueryModifier: React.FC<TextQueryModifierProps> = ({
|
|||
size="icon"
|
||||
className="absolute right-1 top-1 h-8 w-8"
|
||||
onClick={handleClear}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
><X className="h-4 w-4" /></Button>
|
||||
)}
|
||||
</div>
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
size="lg"
|
||||
className="ml-2"
|
||||
onClick={handleSearch}
|
||||
>
|
||||
<Search className="h-4 w-4" />
|
||||
</Button>
|
||||
><Search className="h-4 w-4" /></Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ export const dashboardLanguage = {
|
|||
export const NavigationLanguage = {
|
||||
en: {
|
||||
"/dashboard": "Dashboard",
|
||||
"/append/event": "Event Board",
|
||||
"/append/service": "Service Board",
|
||||
"/append/application": "Application Bind Board",
|
||||
"/append/service": "Service Bind Board",
|
||||
"/application": "Application Board",
|
||||
},
|
||||
tr: {
|
||||
"/dashboard": "Kontrol Paneli",
|
||||
"/append/event": "Event Paneli",
|
||||
"/append/service": "Servis Paneli",
|
||||
"/append/application": "Uygulama Bağlama Paneli",
|
||||
"/append/service": "Servis Bağlama Paneli",
|
||||
"/application": "Uygulama Paneli",
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ function SelectTrigger({
|
|||
>
|
||||
{children}
|
||||
<SelectPrimitive.Icon asChild>
|
||||
<ChevronDownIcon className="size-4 opacity-50" />
|
||||
{/* <ChevronDownIcon className="size-4 opacity-50" /> */}
|
||||
</SelectPrimitive.Icon>
|
||||
</SelectPrimitive.Trigger>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
import {
|
||||
LanguageKey,
|
||||
TranslationSet,
|
||||
} from "@/validations/translations/translation";
|
||||
import {
|
||||
ApplicationBaseTranslationEn,
|
||||
ApplicationBaseTranslationTr,
|
||||
} from "./schemaList/schema";
|
||||
|
||||
// Define translations as a flat object structure to match the common components expectations
|
||||
export const translations = {
|
||||
en: {
|
||||
...ApplicationBaseTranslationEn,
|
||||
// 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
|
||||
...ApplicationBaseTranslationTr,
|
||||
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",
|
||||
},
|
||||
};
|
||||
|
||||
export function getTranslation(lang: LanguageKey): TranslationSet {
|
||||
return translations[lang];
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
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 { ListComponentProps } from './type';
|
||||
|
||||
const ListComponent: React.FC<ListComponentProps> = ({
|
||||
lang,
|
||||
loading,
|
||||
error,
|
||||
data,
|
||||
pagination,
|
||||
showFields,
|
||||
gridCols,
|
||||
handleQueryChange,
|
||||
updatePagination,
|
||||
handleCardClick,
|
||||
handleViewClick,
|
||||
}) => {
|
||||
|
||||
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="name"
|
||||
value={pagination.query["name__ilike"] ? pagination.query["name__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}
|
||||
showUpdateIcon={true}
|
||||
onViewClick={handleViewClick}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ListComponent;
|
||||
|
|
@ -1,9 +1,215 @@
|
|||
"use client";
|
||||
import React from "react";
|
||||
import { PageProps } from "@/validations/translations/translation";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { z } from "zod";
|
||||
|
||||
const AppendersServicePage: React.FC<PageProps> = () => {
|
||||
return <div>AppendersServicePage</div>;
|
||||
import * as schema from "./schemaList/schema";
|
||||
import ListComponent from "./listComponent";
|
||||
import { translations } 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";
|
||||
|
||||
const AppendersServicePage: React.FC<PageProps> = ({ lang }: { lang: Language }) => {
|
||||
|
||||
const {
|
||||
data: dataServices,
|
||||
pagination: paginationServices,
|
||||
loading: loadingServices,
|
||||
error: errorServices,
|
||||
updatePagination: updatePaginationServices,
|
||||
refetch: refetchServices
|
||||
} = useApiData<schema.ApplicationData>('/api/services');
|
||||
const {
|
||||
data: dataEvents,
|
||||
pagination: paginationEvents,
|
||||
loading: loadingEvents,
|
||||
error: errorEvents,
|
||||
updatePagination: updatePaginationEvents,
|
||||
refetch: refetchEvents
|
||||
} = useApiData<schema.ApplicationData>('/api/events');
|
||||
const {
|
||||
data: dataAppenders,
|
||||
pagination: paginationAppenders,
|
||||
loading: loadingAppenders,
|
||||
error: errorAppenders,
|
||||
updatePagination: updatePaginationAppenders,
|
||||
refetch: refetchAppenders
|
||||
} = useApiData<schema.ApplicationData>('/api/appenders');
|
||||
|
||||
const [mode, setMode] = useState<FormModeView | FormMode>("list");
|
||||
const [selectedItemServices, setSelectedItemServices] = useState<schema.ApplicationData | null>(null);
|
||||
const [selectedItemEvents, setSelectedItemEvents] = useState<schema.ApplicationData | null>(null);
|
||||
const [selectedItemAppenders, setSelectedItemAppenders] = useState<schema.ApplicationData | null>(null);
|
||||
const [gridCols, setGridCols] = useState<GridSize>(3);
|
||||
|
||||
const [fieldDefinitionsServices, setFieldDefinitionsServices] = useState<schema.FieldDefinitionsType | null>(null);
|
||||
const [validationSchemaServices, setValidationSchemaServices] = useState<z.ZodSchema | null>(null);
|
||||
const [fieldDefinitionsEvents, setFieldDefinitionsEvents] = useState<schema.FieldDefinitionsType | null>(null);
|
||||
const [validationSchemaEvents, setValidationSchemaEvents] = useState<z.ZodSchema | null>(null);
|
||||
const [fieldDefinitionsAppenders, setFieldDefinitionsAppenders] = useState<schema.FieldDefinitionsType | null>(null);
|
||||
const [validationSchemaAppenders, setValidationSchemaAppenders] = useState<z.ZodSchema | null>(null);
|
||||
|
||||
const showFieldsServices = ["service_name", "service_code", "related_responsibility"];
|
||||
const showFieldsEvents = ["description", "marketing_layer", "cost"];
|
||||
|
||||
useEffect(() => {
|
||||
setFieldDefinitionsServices(schema.viewFieldDefinitions); setValidationSchemaServices(schema.UpdateApplicationSchema);
|
||||
setFieldDefinitionsEvents(schema.viewFieldDefinitions); setValidationSchemaEvents(schema.UpdateApplicationSchema);
|
||||
setFieldDefinitionsAppenders(schema.viewFieldDefinitions); setValidationSchemaAppenders(schema.UpdateApplicationSchema);
|
||||
}, [lang]);
|
||||
|
||||
const handleQueryChange = (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 handleServicesCardClick = (item: schema.ApplicationData) => { console.log("Services Card clicked:", item) };
|
||||
const handleServicesViewClick = (item: schema.ApplicationData) => { setSelectedItemServices(item); setMode("view"); };
|
||||
|
||||
const handleEventsCardClick = (item: schema.ApplicationData) => { console.log("Events Card clicked:", item) };
|
||||
const handleEventsViewClick = (item: schema.ApplicationData) => { setSelectedItemEvents(item); setMode("view"); };
|
||||
|
||||
const handleAppendersCardClick = (item: schema.ApplicationData) => { console.log("Appenders Card clicked:", item) };
|
||||
const handleAppendersViewClick = (item: schema.ApplicationData) => { setSelectedItemAppenders(item); setMode("view"); };
|
||||
|
||||
const cancelAllSelections = () => {
|
||||
setMode("list");
|
||||
setSelectedItemServices(null);
|
||||
setSelectedItemEvents(null);
|
||||
setSelectedItemAppenders(null);
|
||||
};
|
||||
|
||||
const seriveListProps = {
|
||||
lang,
|
||||
loading: loadingServices,
|
||||
error: errorServices,
|
||||
data: dataServices,
|
||||
pagination: paginationServices,
|
||||
showFields: showFieldsServices,
|
||||
gridCols: gridCols,
|
||||
handleQueryChange: handleQueryChange,
|
||||
updatePagination: updatePaginationServices,
|
||||
handleCardClick: handleServicesCardClick,
|
||||
handleViewClick: handleServicesViewClick
|
||||
};
|
||||
|
||||
const eventsListProps = {
|
||||
lang,
|
||||
loading: loadingEvents,
|
||||
error: errorEvents,
|
||||
data: dataEvents,
|
||||
pagination: paginationEvents,
|
||||
showFields: showFieldsEvents,
|
||||
gridCols: gridCols,
|
||||
handleQueryChange: handleQueryChange,
|
||||
updatePagination: updatePaginationEvents,
|
||||
handleCardClick: handleEventsCardClick,
|
||||
handleViewClick: handleEventsViewClick
|
||||
};
|
||||
|
||||
const appendersListProps = {
|
||||
lang,
|
||||
loading: loadingAppenders,
|
||||
error: errorAppenders,
|
||||
data: dataAppenders,
|
||||
pagination: paginationAppenders,
|
||||
showFields: showFieldsEvents,
|
||||
gridCols: gridCols,
|
||||
handleQueryChange: handleQueryChange,
|
||||
updatePagination: updatePaginationAppenders,
|
||||
handleCardClick: handleAppendersCardClick,
|
||||
handleViewClick: handleAppendersViewClick
|
||||
};
|
||||
|
||||
const serviceFormProps = {
|
||||
initialData: selectedItemServices || undefined,
|
||||
mode: mode,
|
||||
refetch: refetchServices,
|
||||
setMode: setMode,
|
||||
setSelectedItem: setSelectedItemServices,
|
||||
onCancel: cancelAllSelections,
|
||||
lang: lang,
|
||||
translations: translations,
|
||||
apiUrl: '/api/services',
|
||||
formProps: {
|
||||
fieldDefinitions: fieldDefinitionsServices,
|
||||
validationSchema: validationSchemaServices,
|
||||
fieldsByMode: schema.fieldsByMode
|
||||
}
|
||||
};
|
||||
|
||||
const eventsFormProps = {
|
||||
initialData: selectedItemEvents || undefined,
|
||||
mode: mode,
|
||||
refetch: refetchEvents,
|
||||
setMode: setMode,
|
||||
setSelectedItem: setSelectedItemEvents,
|
||||
onCancel: cancelAllSelections,
|
||||
lang: lang,
|
||||
translations: translations,
|
||||
apiUrl: '/api/events',
|
||||
formProps: {
|
||||
fieldDefinitions: fieldDefinitionsEvents,
|
||||
validationSchema: validationSchemaEvents,
|
||||
fieldsByMode: schema.fieldsByMode
|
||||
}
|
||||
};
|
||||
|
||||
const appendersFormProps = {
|
||||
initialData: selectedItemAppenders || undefined,
|
||||
mode: mode,
|
||||
refetch: refetchAppenders,
|
||||
setMode: setMode,
|
||||
setSelectedItem: setSelectedItemAppenders,
|
||||
onCancel: cancelAllSelections,
|
||||
lang: lang,
|
||||
translations: translations,
|
||||
apiUrl: '/api/appenders',
|
||||
formProps: {
|
||||
fieldDefinitions: fieldDefinitionsAppenders,
|
||||
validationSchema: validationSchemaAppenders,
|
||||
fieldsByMode: schema.fieldsByMode
|
||||
}
|
||||
};
|
||||
|
||||
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>
|
||||
<div className="flex space-x-4"><GridSelectionComponent gridCols={gridCols} setGridCols={setGridCols} /></div>
|
||||
</div>
|
||||
|
||||
{mode === "list" ? (
|
||||
<div className="flex flex-col space-y-4">
|
||||
{!selectedItemServices ? <div className="w-full h-1/2"><ListComponent {...seriveListProps} /></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?.name}{" "}{translations[lang].serviceSelectedContent}</CardContent>
|
||||
</Card>
|
||||
<div className="flex flex-row space-x-4">
|
||||
<div className="flex-1"><ListComponent {...eventsListProps} /></div>
|
||||
<div className="flex-1"><ListComponent {...appendersListProps} /></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col space-y-4">
|
||||
{selectedItemServices && <FormDisplay<schema.ApplicationData> {...serviceFormProps} />}
|
||||
{selectedItemEvents && <FormDisplay<schema.ApplicationData> {...eventsFormProps} />}
|
||||
{selectedItemAppenders && <FormDisplay<schema.ApplicationData> {...appendersFormProps} />}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppendersServicePage;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,476 @@
|
|||
import { z } from "zod";
|
||||
import { flattenFieldDefinitions } from "@/eventRouters/schemas/zodSchemas";
|
||||
|
||||
export interface ApplicationData {
|
||||
id?: number;
|
||||
name: string;
|
||||
application_code: string;
|
||||
site_url: string;
|
||||
application_type: string;
|
||||
application_for?: string;
|
||||
description?: string;
|
||||
active: boolean;
|
||||
deleted?: boolean;
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
}
|
||||
|
||||
// Validation error messages by language
|
||||
const errorMessages = {
|
||||
en: {
|
||||
nameRequired: "Name is required",
|
||||
applicationCodeRequired: "Application code is required",
|
||||
siteUrlRequired: "Site URL is required",
|
||||
applicationTypeRequired: "Application type is required",
|
||||
},
|
||||
tr: {
|
||||
nameRequired: "İsim gereklidir",
|
||||
applicationCodeRequired: "Uygulama kodu gereklidir",
|
||||
siteUrlRequired: "Site URL'si gereklidir",
|
||||
applicationTypeRequired: "Uygulama tipi gereklidir",
|
||||
},
|
||||
};
|
||||
|
||||
// Function to get schema with language-specific validation messages
|
||||
const getApplicationBaseSchema = (lang: "en" | "tr" = "en") =>
|
||||
z.object({
|
||||
// Identification fields
|
||||
uu_id: z.string().optional(),
|
||||
name: z.string().min(1, errorMessages[lang].nameRequired),
|
||||
application_code: z
|
||||
.string()
|
||||
.min(1, errorMessages[lang].applicationCodeRequired),
|
||||
|
||||
// Application details
|
||||
site_url: z.string().min(1, errorMessages[lang].siteUrlRequired),
|
||||
application_type: z
|
||||
.string()
|
||||
.min(1, errorMessages[lang].applicationTypeRequired),
|
||||
application_for: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
|
||||
// Status fields
|
||||
active: z.boolean().default(true),
|
||||
deleted: z.boolean().default(false),
|
||||
|
||||
// System fields
|
||||
created_at: z.string().optional(),
|
||||
updated_at: z.string().optional(),
|
||||
});
|
||||
|
||||
// For backward compatibility
|
||||
const ApplicationBaseSchema = getApplicationBaseSchema("en");
|
||||
|
||||
export const ApplicationBaseTranslationTr = {
|
||||
uu_id: "UUID",
|
||||
name: "Name",
|
||||
application_code: "Application Code",
|
||||
site_url: "Site URL",
|
||||
application_type: "Application Type",
|
||||
application_for: "Application For",
|
||||
description: "Description",
|
||||
active: "Active",
|
||||
deleted: "Deleted",
|
||||
created_at: "Created At",
|
||||
updated_at: "Updated At",
|
||||
};
|
||||
|
||||
export const ApplicationBaseTranslationEn = {
|
||||
uu_id: "UUID",
|
||||
name: "Name",
|
||||
application_code: "Application Code",
|
||||
site_url: "Site URL",
|
||||
application_type: "Application Type",
|
||||
application_for: "Application For",
|
||||
description: "Description",
|
||||
active: "Active",
|
||||
deleted: "Deleted",
|
||||
created_at: "Created At",
|
||||
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,
|
||||
created_at: true,
|
||||
updated_at: true,
|
||||
deleted: true,
|
||||
});
|
||||
|
||||
// Update schema for updating existing applications with language support
|
||||
const getUpdateApplicationSchema = (lang: "en" | "tr" = "en") =>
|
||||
getApplicationBaseSchema(lang)
|
||||
.omit({
|
||||
created_at: true,
|
||||
updated_at: true,
|
||||
deleted: true,
|
||||
})
|
||||
.required({
|
||||
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,
|
||||
};
|
||||
|
||||
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>;
|
||||
|
||||
// Base field definitions grouped by section
|
||||
const baseFieldDefinitions = {
|
||||
// Identification fields
|
||||
identificationInfo: {
|
||||
title: "Identification Information",
|
||||
order: 1,
|
||||
fields: {
|
||||
uu_id: {
|
||||
type: "text",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.uu_id,
|
||||
en: ApplicationBaseTranslationEn.uu_id,
|
||||
},
|
||||
readOnly: true,
|
||||
required: false,
|
||||
},
|
||||
name: {
|
||||
type: "text",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.name,
|
||||
en: ApplicationBaseTranslationEn.name,
|
||||
},
|
||||
readOnly: false,
|
||||
required: true,
|
||||
},
|
||||
application_code: {
|
||||
type: "text",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.application_code,
|
||||
en: ApplicationBaseTranslationEn.application_code,
|
||||
},
|
||||
readOnly: false,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Application details
|
||||
applicationDetails: {
|
||||
title: "Application Details",
|
||||
order: 2,
|
||||
fields: {
|
||||
site_url: {
|
||||
type: "text",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.site_url,
|
||||
en: ApplicationBaseTranslationEn.site_url,
|
||||
},
|
||||
readOnly: false,
|
||||
required: true,
|
||||
},
|
||||
application_type: {
|
||||
type: "select",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.application_type,
|
||||
en: ApplicationBaseTranslationEn.application_type,
|
||||
},
|
||||
options: ["info", "Dash", "Admin"],
|
||||
readOnly: false,
|
||||
required: true,
|
||||
},
|
||||
application_for: {
|
||||
type: "select",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.application_for,
|
||||
en: ApplicationBaseTranslationEn.application_for,
|
||||
},
|
||||
options: ["EMP", "OCC"],
|
||||
readOnly: false,
|
||||
required: false,
|
||||
},
|
||||
description: {
|
||||
type: "textarea",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.description,
|
||||
en: ApplicationBaseTranslationEn.description,
|
||||
},
|
||||
readOnly: false,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Status fields
|
||||
statusInfo: {
|
||||
title: "Status Information",
|
||||
order: 3,
|
||||
fields: {
|
||||
active: {
|
||||
type: "checkbox",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.active,
|
||||
en: ApplicationBaseTranslationEn.active,
|
||||
},
|
||||
readOnly: false,
|
||||
required: false,
|
||||
defaultValue: true,
|
||||
},
|
||||
deleted: {
|
||||
type: "checkbox",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.deleted,
|
||||
en: ApplicationBaseTranslationEn.deleted,
|
||||
},
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// System fields
|
||||
systemInfo: {
|
||||
title: "System Information",
|
||||
order: 4,
|
||||
fields: {
|
||||
created_at: {
|
||||
type: "date",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.created_at,
|
||||
en: ApplicationBaseTranslationEn.created_at,
|
||||
},
|
||||
readOnly: true,
|
||||
required: false,
|
||||
},
|
||||
updated_at: {
|
||||
type: "date",
|
||||
label: {
|
||||
tr: ApplicationBaseTranslationTr.updated_at,
|
||||
en: ApplicationBaseTranslationEn.updated_at,
|
||||
},
|
||||
readOnly: true,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Create a flat version of the field definitions for compatibility
|
||||
const flatFieldDefinitions = flattenFieldDefinitions(baseFieldDefinitions);
|
||||
|
||||
// Create mode-specific field definitions using the flattened structure
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
// Update mode-specific field definitions
|
||||
export const updateFieldDefinitions = {
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
// View mode-specific field definitions
|
||||
export const viewFieldDefinitions = {
|
||||
uu_id: {
|
||||
...flatFieldDefinitions.uu_id,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
name: {
|
||||
...flatFieldDefinitions.name,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: "",
|
||||
},
|
||||
application_code: {
|
||||
...flatFieldDefinitions.application_code,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: "",
|
||||
},
|
||||
site_url: {
|
||||
...flatFieldDefinitions.site_url,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: "",
|
||||
},
|
||||
application_type: {
|
||||
...flatFieldDefinitions.application_type,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: "",
|
||||
},
|
||||
application_for: {
|
||||
...flatFieldDefinitions.application_for,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: "",
|
||||
},
|
||||
description: {
|
||||
...flatFieldDefinitions.description,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: "",
|
||||
},
|
||||
active: {
|
||||
...flatFieldDefinitions.active,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: true,
|
||||
},
|
||||
deleted: {
|
||||
...flatFieldDefinitions.deleted,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
created_at: {
|
||||
...flatFieldDefinitions.created_at,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: "",
|
||||
},
|
||||
updated_at: {
|
||||
...flatFieldDefinitions.updated_at,
|
||||
readOnly: true,
|
||||
required: false,
|
||||
defaultValue: "",
|
||||
},
|
||||
};
|
||||
|
||||
// Combined field definitions for all modes
|
||||
export const fieldDefinitions = {
|
||||
...baseFieldDefinitions,
|
||||
getDefinitionsByMode: (mode: "create" | "update" | "view") => {
|
||||
switch (mode) {
|
||||
case "create":
|
||||
return createFieldDefinitions;
|
||||
case "update":
|
||||
return updateFieldDefinitions;
|
||||
case "view":
|
||||
return viewFieldDefinitions;
|
||||
default:
|
||||
return baseFieldDefinitions;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// 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),
|
||||
};
|
||||
|
||||
export type FieldDefinitionsType =
|
||||
| typeof createFieldDefinitions
|
||||
| typeof updateFieldDefinitions
|
||||
| typeof viewFieldDefinitions;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { Language } from "@/components/common/schemas";
|
||||
import { GridSize } from "@/components/common/HeaderSelections/GridSelectionComponent";
|
||||
import * as schema from "./schemaList/schema";
|
||||
|
||||
export interface ListComponentProps {
|
||||
lang: Language;
|
||||
loading: boolean;
|
||||
error: any;
|
||||
data: schema.ApplicationData[];
|
||||
pagination: any;
|
||||
showFields: string[];
|
||||
gridCols: GridSize;
|
||||
handleQueryChange: (key: string, value: string | null) => void;
|
||||
updatePagination: (pagination: any) => void;
|
||||
handleCardClick: (item: schema.ApplicationData) => void;
|
||||
handleViewClick: (item: schema.ApplicationData) => void;
|
||||
}
|
||||
|
|
@ -2,42 +2,17 @@ import {
|
|||
LanguageKey,
|
||||
TranslationSet,
|
||||
} from "@/validations/translations/translation";
|
||||
|
||||
export const fieldLanguageTranslation = {
|
||||
tr: {
|
||||
uu_id: "UUID",
|
||||
name: "Ad",
|
||||
application_code: "Kod",
|
||||
site_url: "URL",
|
||||
application_type: "Tür",
|
||||
application_for: "Uygulama için",
|
||||
description: "Açıklama",
|
||||
active: "Aktif",
|
||||
deleted: "Silindi",
|
||||
created_at: "Oluşturulma Tarihi",
|
||||
updated_at: "Güncellenme Tarihi",
|
||||
},
|
||||
en: {
|
||||
uu_id: "UUID",
|
||||
name: "Name",
|
||||
application_code: "Code",
|
||||
site_url: "URL",
|
||||
application_type: "Type",
|
||||
application_for: "Application for",
|
||||
description: "Description",
|
||||
active: "Active",
|
||||
deleted: "Deleted",
|
||||
created_at: "Created At",
|
||||
updated_at: "Updated At",
|
||||
},
|
||||
};
|
||||
import {
|
||||
ApplicationBaseTranslationEn,
|
||||
ApplicationBaseTranslationTr,
|
||||
} from "./schema";
|
||||
|
||||
// Define translations as a flat object structure to match the common components expectations
|
||||
export const translations = {
|
||||
en: {
|
||||
...fieldLanguageTranslation.en,
|
||||
...ApplicationBaseTranslationEn,
|
||||
// Page title
|
||||
applicationTitle: "Applications",
|
||||
title: "Applications",
|
||||
|
||||
// Common actions
|
||||
create: "Create",
|
||||
|
|
@ -108,8 +83,8 @@ export const translations = {
|
|||
},
|
||||
tr: {
|
||||
// Page title
|
||||
...fieldLanguageTranslation.tr,
|
||||
applicationTitle: "Uygulamalar",
|
||||
...ApplicationBaseTranslationTr,
|
||||
title: "Uygulamalar",
|
||||
|
||||
// Common actions
|
||||
create: "Oluştur",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
"use client";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import * as schema from "./schema";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Building, Filter, User } from "lucide-react";
|
||||
import { TypeQueryModifier } from "@/components/common/QueryModifiers/TypeQueryModifier";
|
||||
|
|
@ -12,7 +14,6 @@ import { CardDisplay } from "@/components/common/CardDisplay/CardDisplay";
|
|||
import { FormMode } from "@/components/common/FormDisplay/types";
|
||||
import { FormDisplay } from "@/components/common/FormDisplay/FormDisplay";
|
||||
import { GridSelectionComponent, GridSize } from "@/components/common/HeaderSelections/GridSelectionComponent";
|
||||
import { LanguageSelectionComponent } from "@/components/common/HeaderSelections/LanguageSelectionComponent";
|
||||
import { getCreateApplicationSchema, getUpdateApplicationSchema } from "./schema";
|
||||
import { translations } from "./language";
|
||||
import { PageProps } from "@/validations/translations/translation";
|
||||
|
|
@ -21,64 +22,34 @@ 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');
|
||||
|
||||
// State for managing view/edit modes
|
||||
const [mode, setMode] = useState<FormMode>("list");
|
||||
const [selectedItem, setSelectedItem] = useState<schema.ApplicationData | null>(null);
|
||||
const [gridCols, setGridCols] = useState<GridSize>(3);
|
||||
const [fieldDefinitions, setFieldDefinitions] = useState<schema.FieldDefinitionsType | null>(null);
|
||||
const [validationSchema, setValidationSchema] = useState<z.ZodSchema | null>(null);
|
||||
|
||||
// Use state to store the field definitions and validation schema
|
||||
const [fieldDefinitions, setFieldDefinitions] = useState(() =>
|
||||
mode === 'create' ? schema.createFieldDefinitions :
|
||||
mode === 'update' ? schema.updateFieldDefinitions :
|
||||
schema.viewFieldDefinitions
|
||||
);
|
||||
|
||||
const [validationSchema, setValidationSchema] = useState(() =>
|
||||
mode === 'create' ? getCreateApplicationSchema(lang) :
|
||||
mode === 'update' ? getUpdateApplicationSchema(lang) :
|
||||
schema.ViewApplicationSchema
|
||||
);
|
||||
|
||||
// Update field definitions when mode changes
|
||||
useEffect(() => {
|
||||
// Select the appropriate field definitions based on the current mode
|
||||
const newFieldDefs = mode === 'create' ? schema.createFieldDefinitions :
|
||||
mode === 'update' ? schema.updateFieldDefinitions :
|
||||
schema.viewFieldDefinitions;
|
||||
|
||||
setFieldDefinitions(newFieldDefs);
|
||||
}, [mode]);
|
||||
|
||||
// Update validation schema when mode or language changes
|
||||
useEffect(() => {
|
||||
setValidationSchema(
|
||||
mode === 'create' ? getCreateApplicationSchema(lang) :
|
||||
mode === 'update' ? getUpdateApplicationSchema(lang) :
|
||||
schema.ViewApplicationSchema
|
||||
);
|
||||
if (mode === 'create') {
|
||||
setFieldDefinitions(schema.createFieldDefinitions);
|
||||
setValidationSchema(getCreateApplicationSchema(lang));
|
||||
} else if (mode === 'update') {
|
||||
setFieldDefinitions(schema.updateFieldDefinitions);
|
||||
setValidationSchema(getUpdateApplicationSchema(lang));
|
||||
} else {
|
||||
setFieldDefinitions(schema.viewFieldDefinitions);
|
||||
setValidationSchema(schema.ViewApplicationSchema);
|
||||
}
|
||||
}, [mode, lang]);
|
||||
|
||||
|
||||
// Fields to display in the cards
|
||||
const showFields = ["application_code", "site_url", "application_type"];
|
||||
|
||||
// Search options
|
||||
const searchOptions = {
|
||||
typeOptions: [
|
||||
{
|
||||
value: "EMP",
|
||||
label: translations[lang].employee,
|
||||
icon: <User className="mr-2 h-4 w-4" />
|
||||
|
||||
},
|
||||
{
|
||||
value: "OCC",
|
||||
|
|
@ -107,67 +78,61 @@ const ApplicationPage: React.FC<PageProps> = ({ lang }: { lang: Language }) => {
|
|||
]
|
||||
};
|
||||
|
||||
// Handle query changes
|
||||
const handleQueryChange = (key: string, value: string | null) => {
|
||||
const newQuery = { ...pagination.query };
|
||||
|
||||
if (value === null) {
|
||||
// Remove the key if value is null
|
||||
delete newQuery[key];
|
||||
} else if (value.trim() === "") {
|
||||
// Remove the key if value is empty string
|
||||
delete newQuery[key];
|
||||
} else {
|
||||
// Add/update the key with the value
|
||||
newQuery[key] = value;
|
||||
}
|
||||
|
||||
updatePagination({
|
||||
page: 1, // Reset to first page on new search
|
||||
query: newQuery,
|
||||
});
|
||||
if (value === null) { delete newQuery[key]; } else if (value.trim() === "") { delete newQuery[key]; } else { newQuery[key] = value; }
|
||||
updatePagination({ page: 1, query: newQuery });
|
||||
};
|
||||
const handleCardClick = (item: schema.ApplicationData) => { console.log("Card clicked:", item) };
|
||||
const handleViewClick = (item: schema.ApplicationData) => { setSelectedItem(item); setMode("view"); };
|
||||
const handleUpdateClick = (item: schema.ApplicationData) => { setSelectedItem(item); setTimeout(() => { setMode("update") }, 0); };
|
||||
const handleCreateClick = () => { setSelectedItem(null); setMode("create"); };
|
||||
|
||||
|
||||
// Handle card actions
|
||||
const handleCardClick = (item: schema.ApplicationData) => {
|
||||
console.log("Card clicked:", item);
|
||||
};
|
||||
|
||||
const handleViewClick = (item: schema.ApplicationData) => {
|
||||
setSelectedItem(item);
|
||||
setMode("view");
|
||||
};
|
||||
|
||||
const handleUpdateClick = (item: schema.ApplicationData) => {
|
||||
setSelectedItem(item);
|
||||
setTimeout(() => {
|
||||
setMode("update");
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// Handle create button click
|
||||
const handleCreateClick = () => {
|
||||
const cancelAllSelections = () => {
|
||||
setSelectedItem(null);
|
||||
setMode("create");
|
||||
};
|
||||
|
||||
// Handle cancel
|
||||
const handleCancel = () => {
|
||||
setMode("list");
|
||||
setSelectedItem(null);
|
||||
};
|
||||
|
||||
const applicationCardDisplayProps = {
|
||||
showFields: showFields,
|
||||
data: data,
|
||||
lang: lang,
|
||||
translations: translations,
|
||||
error: error,
|
||||
loading: loading,
|
||||
titleField: "name",
|
||||
onCardClick: handleCardClick,
|
||||
gridCols: gridCols,
|
||||
showViewIcon: true,
|
||||
showUpdateIcon: true,
|
||||
onViewClick: handleViewClick,
|
||||
onUpdateClick: handleUpdateClick
|
||||
};
|
||||
|
||||
const applicationFormProps = {
|
||||
initialData: selectedItem || undefined,
|
||||
mode,
|
||||
refetch,
|
||||
setMode,
|
||||
setSelectedItem,
|
||||
onCancel: cancelAllSelections,
|
||||
lang,
|
||||
translations,
|
||||
apiUrl: '/api/applications',
|
||||
formProps: {
|
||||
fieldDefinitions,
|
||||
validationSchema,
|
||||
fieldsByMode: schema.fieldsByMode
|
||||
}
|
||||
}
|
||||
|
||||
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].applicationTitle || "Applications"}</h1>
|
||||
<h1 className="text-2xl font-bold">{translations[lang].title}</h1>
|
||||
<div className="flex space-x-4">
|
||||
{/* Grid Selection */}
|
||||
<GridSelectionComponent
|
||||
gridCols={gridCols}
|
||||
setGridCols={setGridCols}
|
||||
/>
|
||||
<GridSelectionComponent gridCols={gridCols} setGridCols={setGridCols} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -193,42 +158,23 @@ const ApplicationPage: React.FC<PageProps> = ({ lang }: { lang: Language }) => {
|
|||
{/* Filters on the right */}
|
||||
<div className={`w-full ${searchOptions.typeOptions.length > 0 ? 'md:w-1/2 md:pl-4' : ''} 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 || "Filter Selection"}
|
||||
</div>
|
||||
{/* <Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleResetAllFilters}
|
||||
className="text-xs"
|
||||
>
|
||||
{translations[lang].resetAll || "Reset All"}
|
||||
</Button> */}
|
||||
<div className="flex items-center"><Filter className="mr-2 h-4 w-4" />{translations[lang].filterSelection}</div>
|
||||
</div>
|
||||
|
||||
{/* Search input */}
|
||||
<TextQueryModifier
|
||||
fieldKey="name"
|
||||
value={pagination.query["name__ilike"] ? pagination.query["name__ilike"].replace(/%/g, "") : ""}
|
||||
label={translations[lang].search || "Search"}
|
||||
onQueryChange={handleQueryChange}
|
||||
translations={translations}
|
||||
lang={lang}
|
||||
/>
|
||||
<TextQueryModifier fieldKey="name" value={pagination.query["name__ilike"] ? pagination.query["name__ilike"].replace(/%/g, "") : ""} label={translations[lang].search} onQueryChange={handleQueryChange} translations={translations} lang={lang} />
|
||||
|
||||
{/* Site URL dropdown */}
|
||||
{searchOptions.urlOptions.length > 0 && (
|
||||
<SelectQueryModifier
|
||||
fieldKey="site_url"
|
||||
{
|
||||
searchOptions.urlOptions.length > 0 && <SelectQueryModifier fieldKey="site_url"
|
||||
value={pagination.query["site_url__ilike"] ? pagination.query["site_url__ilike"].replace(/%/g, "") : ""}
|
||||
label={translations[lang].siteUrl || "Site URL"}
|
||||
label={translations[lang].siteUrl}
|
||||
options={searchOptions.urlOptions.map(url => ({ value: url, label: url }))}
|
||||
onQueryChange={handleQueryChange}
|
||||
translations={translations}
|
||||
lang={lang}
|
||||
/>
|
||||
)}
|
||||
}
|
||||
|
||||
{/* Additional fields */}
|
||||
{/* {searchOptions.additionalFields && searchOptions.additionalFields?.map(field => (
|
||||
|
|
@ -249,65 +195,26 @@ const ApplicationPage: React.FC<PageProps> = ({ lang }: { lang: Language }) => {
|
|||
</Card>
|
||||
|
||||
{/* Create Button */}
|
||||
<Card className="my-4">
|
||||
<CardContent className="pt-6">
|
||||
<CreateButton
|
||||
<Card className="my-4"><CardContent className="pt-6"><CreateButton
|
||||
onClick={handleCreateClick}
|
||||
translations={translations}
|
||||
lang={lang}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
/></CardContent></Card>
|
||||
|
||||
{/* Pagination Tools Component */}
|
||||
<Card className="my-4">
|
||||
<CardContent className="pt-6">
|
||||
<PaginationToolsComponent
|
||||
<Card className="my-4"><CardContent className="pt-6"><PaginationToolsComponent
|
||||
pagination={pagination}
|
||||
updatePagination={updatePagination}
|
||||
loading={loading}
|
||||
lang={lang}
|
||||
translations={translations}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
/></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}
|
||||
showUpdateIcon={true}
|
||||
onViewClick={handleViewClick}
|
||||
onUpdateClick={handleUpdateClick}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-6"><CardDisplay {...applicationCardDisplayProps} /></div>
|
||||
</>
|
||||
) : (
|
||||
<FormDisplay<schema.ApplicationData>
|
||||
initialData={selectedItem || undefined}
|
||||
mode={mode}
|
||||
refetch={refetch}
|
||||
setMode={setMode}
|
||||
setSelectedItem={setSelectedItem}
|
||||
onCancel={handleCancel}
|
||||
lang={lang}
|
||||
translations={translations}
|
||||
apiUrl='/api/applications'
|
||||
formProps={{
|
||||
fieldDefinitions,
|
||||
validationSchema,
|
||||
fieldsByMode: schema.fieldsByMode
|
||||
}}
|
||||
/>
|
||||
<FormDisplay<schema.ApplicationData> {...applicationFormProps} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { z } from "zod";
|
||||
import { flattenFieldDefinitions } from "../schemas/zodSchemas";
|
||||
import { flattenFieldDefinitions } from "@/eventRouters/schemas/zodSchemas";
|
||||
|
||||
export interface ApplicationData {
|
||||
id?: number;
|
||||
|
|
@ -21,26 +21,31 @@ const errorMessages = {
|
|||
nameRequired: "Name is required",
|
||||
applicationCodeRequired: "Application code is required",
|
||||
siteUrlRequired: "Site URL is required",
|
||||
applicationTypeRequired: "Application type is required"
|
||||
applicationTypeRequired: "Application type is required",
|
||||
},
|
||||
tr: {
|
||||
nameRequired: "İsim gereklidir",
|
||||
applicationCodeRequired: "Uygulama kodu gereklidir",
|
||||
siteUrlRequired: "Site URL'si gereklidir",
|
||||
applicationTypeRequired: "Uygulama tipi gereklidir"
|
||||
}
|
||||
applicationTypeRequired: "Uygulama tipi gereklidir",
|
||||
},
|
||||
};
|
||||
|
||||
// Function to get schema with language-specific validation messages
|
||||
const getApplicationBaseSchema = (lang: "en" | "tr" = "en") => z.object({
|
||||
const getApplicationBaseSchema = (lang: "en" | "tr" = "en") =>
|
||||
z.object({
|
||||
// Identification fields
|
||||
uu_id: z.string().optional(),
|
||||
name: z.string().min(1, errorMessages[lang].nameRequired),
|
||||
application_code: z.string().min(1, errorMessages[lang].applicationCodeRequired),
|
||||
application_code: z
|
||||
.string()
|
||||
.min(1, errorMessages[lang].applicationCodeRequired),
|
||||
|
||||
// Application details
|
||||
site_url: z.string().min(1, errorMessages[lang].siteUrlRequired),
|
||||
application_type: z.string().min(1, errorMessages[lang].applicationTypeRequired),
|
||||
application_type: z
|
||||
.string()
|
||||
.min(1, errorMessages[lang].applicationTypeRequired),
|
||||
application_for: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
|
||||
|
|
@ -56,7 +61,7 @@ const getApplicationBaseSchema = (lang: "en" | "tr" = "en") => z.object({
|
|||
// For backward compatibility
|
||||
const ApplicationBaseSchema = getApplicationBaseSchema("en");
|
||||
|
||||
const ApplicationBaseTranslationTr = {
|
||||
export const ApplicationBaseTranslationTr = {
|
||||
uu_id: "UUID",
|
||||
name: "Name",
|
||||
application_code: "Application Code",
|
||||
|
|
@ -70,7 +75,7 @@ const ApplicationBaseTranslationTr = {
|
|||
updated_at: "Updated At",
|
||||
};
|
||||
|
||||
const ApplicationBaseTranslationEn = {
|
||||
export const ApplicationBaseTranslationEn = {
|
||||
uu_id: "UUID",
|
||||
name: "Name",
|
||||
application_code: "Application Code",
|
||||
|
|
@ -95,11 +100,13 @@ const getCreateApplicationSchema = (lang: "en" | "tr" = "en") =>
|
|||
|
||||
// Update schema for updating existing applications with language support
|
||||
const getUpdateApplicationSchema = (lang: "en" | "tr" = "en") =>
|
||||
getApplicationBaseSchema(lang).omit({
|
||||
getApplicationBaseSchema(lang)
|
||||
.omit({
|
||||
created_at: true,
|
||||
updated_at: true,
|
||||
deleted: true,
|
||||
}).required({
|
||||
})
|
||||
.required({
|
||||
uu_id: true,
|
||||
});
|
||||
|
||||
|
|
@ -462,3 +469,8 @@ export const fieldsByMode = {
|
|||
update: Object.keys(updateFieldDefinitions),
|
||||
view: Object.keys(viewFieldDefinitions),
|
||||
};
|
||||
|
||||
export type FieldDefinitionsType =
|
||||
| typeof createFieldDefinitions
|
||||
| typeof updateFieldDefinitions
|
||||
| typeof viewFieldDefinitions;
|
||||
|
|
|
|||
Loading…
Reference in New Issue