diff --git a/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx b/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx index 7cf3d63e42..bd8afb879d 100644 --- a/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx +++ b/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx @@ -1,5 +1,4 @@ -import type { VFC } from 'react'; -import type { ChangeRequestType } from '../changeRequest.types'; +import type { FC } from 'react'; import { Badge } from 'component/common/Badge/Badge'; import AccessTime from '@mui/icons-material/AccessTime'; import Check from '@mui/icons-material/Check'; @@ -9,20 +8,27 @@ import ErrorIcon from '@mui/icons-material/Error'; import PauseCircle from '@mui/icons-material/PauseCircle'; import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip'; import { useLocationSettings } from 'hooks/useLocationSettings'; +import type { + ScheduledChangeRequest, + UnscheduledChangeRequest, +} from '../changeRequest.types'; -interface IChangeRequestStatusBadgeProps { - changeRequest: ChangeRequestType | undefined; +export interface IChangeRequestStatusBadgeProps { + changeRequest: + | Pick + | Pick + | undefined; } -const ReviewRequiredBadge: VFC = () => ( +const ReviewRequiredBadge: FC = () => ( }> Review required ); -const DraftBadge: VFC = () => Draft; +const DraftBadge: FC = () => Draft; -export const ChangeRequestStatusBadge: VFC = ({ +export const ChangeRequestStatusBadge: FC = ({ changeRequest, }) => { const { locationSettings } = useLocationSettings(); diff --git a/frontend/src/component/changeRequest/ChangeRequests/ChangeRequests.tsx b/frontend/src/component/changeRequest/ChangeRequests/ChangeRequests.tsx index 0d61ef542d..8d634a6fcc 100644 --- a/frontend/src/component/changeRequest/ChangeRequests/ChangeRequests.tsx +++ b/frontend/src/component/changeRequest/ChangeRequests/ChangeRequests.tsx @@ -13,32 +13,34 @@ import { useUiFlag } from 'hooks/useUiFlag.js'; import { ChangeRequestFilters } from './ChangeRequestFilters.tsx'; import { withTableState } from 'utils/withTableState'; import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser'; -import { - useChangeRequestsWithMockData as useChangeRequests, - type ChangeRequestItem -} from 'hooks/api/getters/useChangeRequests/useChangeRequests'; import { - encodeQueryParams, + useChangeRequestSearch, + DEFAULT_PAGE_LIMIT, +} from 'hooks/api/getters/useChangeRequestSearch/useChangeRequestSearch'; +import type { ChangeRequestSearchItemSchema } from 'openapi'; +import { NumberParam, StringParam, withDefault, useQueryParams, } from 'use-query-params'; -import mapValues from 'lodash.mapvalues'; import useLoading from 'hooks/useLoading'; import { styles as themeStyles } from 'component/common'; import { FilterItemParam } from 'utils/serializeQueryParams'; -const DEFAULT_PAGE_LIMIT = 25; -const columnHelper = createColumnHelper(); +const columnHelper = createColumnHelper(); const ChangeRequestsInner = () => { const { user } = useAuthUser(); - + // Check URL parameters directly to avoid double fetching const shouldApplyDefaults = useMemo(() => { const urlParams = new URLSearchParams(window.location.search); - return !urlParams.has('createdBy') && !urlParams.has('requestedApprovalBy') && user; + return ( + !urlParams.has('createdBy') && + !urlParams.has('requestedApproverId') && + user + ); }, [user]); const stateConfig = { @@ -47,38 +49,37 @@ const ChangeRequestsInner = () => { sortBy: withDefault(StringParam, 'createdAt'), sortOrder: withDefault(StringParam, 'desc'), createdBy: FilterItemParam, - requestedApprovalBy: FilterItemParam, + requestedApproverId: FilterItemParam, }; // Apply initial defaults if needed - const initialState = shouldApplyDefaults ? { - createdBy: { - operator: 'IS' as const, - values: [user.id.toString()], - } - } : {}; - - const [tableState, setTableState] = useQueryParams( - stateConfig, - { updateType: 'replaceIn' }, - ); + const initialState = shouldApplyDefaults + ? { + createdBy: { + operator: 'IS' as const, + values: user ? [user.id.toString()] : [], + }, + } + : {}; + + const [tableState, setTableState] = useQueryParams(stateConfig, { + updateType: 'replaceIn', + }); // Merge with initial state on first load only - const effectiveTableState = useMemo(() => ({ - ...initialState, - ...tableState - }), [initialState, tableState]); + const effectiveTableState = useMemo( + () => ({ + ...initialState, + ...tableState, + }), + [initialState, tableState], + ); const { changeRequests: data, total, loading, - initialLoad, - } = useChangeRequests( - mapValues(encodeQueryParams(stateConfig, effectiveTableState), (value) => - value ? `${value}` : undefined, - ), - ); + } = useChangeRequestSearch(effectiveTableState); const columns = useMemo( () => [ @@ -87,8 +88,8 @@ const ChangeRequestsInner = () => { header: 'Title', meta: { width: '300px' }, cell: ({ getValue, row }) => ( - ), @@ -105,12 +106,14 @@ const ChangeRequestsInner = () => { }) => { const features = getValue(); // Convert string array to object array for FeaturesCell compatibility - const featureObjects = features.map((name: string) => ({ name })); + const featureObjects = features.map((name: string) => ({ + name, + })); return ( - ); }, @@ -120,31 +123,26 @@ const ChangeRequestsInner = () => { header: 'By', meta: { width: '180px', align: 'left' }, enableSorting: false, - cell: ({ getValue }) => ( - - ), + cell: ({ getValue }) => , }), columnHelper.accessor('createdAt', { id: 'Submitted', header: 'Submitted', meta: { width: '100px' }, - cell: ({ getValue }) => ( - - ), + cell: ({ getValue }) => , }), columnHelper.accessor('environment', { id: 'Environment', header: 'Environment', meta: { width: '100px' }, - cell: ({ getValue }) => ( - - ), + cell: ({ getValue }) => , }), columnHelper.accessor('state', { id: 'Status', header: 'Status', meta: { width: '170px' }, cell: ({ getValue, row }) => ( + // @ts-expect-error (`globalChangeRequestList`) The schema (and query) needs to be updated ), }), @@ -166,9 +164,9 @@ const ChangeRequestsInner = () => { bodyClass='no-padding' header={} > -
@@ -189,4 +187,4 @@ export const ChangeRequests = () => { } return ; -}; \ No newline at end of file +}; diff --git a/frontend/src/component/changeRequest/ChangeRequests/GlobalChangeRequestTitleCell.tsx b/frontend/src/component/changeRequest/ChangeRequests/GlobalChangeRequestTitleCell.tsx index 678c2a0918..17f0b1275a 100644 --- a/frontend/src/component/changeRequest/ChangeRequests/GlobalChangeRequestTitleCell.tsx +++ b/frontend/src/component/changeRequest/ChangeRequests/GlobalChangeRequestTitleCell.tsx @@ -1,6 +1,7 @@ import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; import { Link, styled, Typography } from '@mui/material'; import { Link as RouterLink, type LinkProps } from 'react-router-dom'; +import { useProjectOverviewNameOrId } from 'hooks/api/getters/useProjectOverview/useProjectOverview'; type IGlobalChangeRequestTitleCellProps = { value?: any; @@ -41,12 +42,12 @@ export const GlobalChangeRequestTitleCell = ({ id, title, project, - projectName, features: featureChanges, segments: segmentChanges, } = original; + const projectName = useProjectOverviewNameOrId(project); const totalChanges = - (featureChanges || []).length + (segmentChanges || []).length; + featureChanges?.length ?? 0 + segmentChanges?.length ?? 0; const projectPath = `/projects/${project}`; const crPath = `${projectPath}/change-requests/${id}`; diff --git a/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestStatusCell.tsx b/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestStatusCell.tsx index 734a3f1fcc..84f7bc2618 100644 --- a/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestStatusCell.tsx +++ b/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestStatusCell.tsx @@ -1,14 +1,18 @@ -import type { VFC } from 'react'; import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; -import type { ChangeRequestType } from 'component/changeRequest/changeRequest.types'; -import { ChangeRequestStatusBadge } from 'component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge'; +import { + ChangeRequestStatusBadge, + type IChangeRequestStatusBadgeProps, +} from 'component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge'; +import type { FC } from 'react'; interface IChangeRequestStatusCellProps { value?: string | null; // FIXME: proper type - row: { original: ChangeRequestType }; + row: { + original: IChangeRequestStatusBadgeProps['changeRequest']; + }; } -export const ChangeRequestStatusCell: VFC = ({ +export const ChangeRequestStatusCell: FC = ({ value, row: { original }, }) => { diff --git a/frontend/src/hooks/api/getters/useChangeRequestSearch/useChangeRequestSearch.ts b/frontend/src/hooks/api/getters/useChangeRequestSearch/useChangeRequestSearch.ts index fca192d487..3ac7d4966c 100644 --- a/frontend/src/hooks/api/getters/useChangeRequestSearch/useChangeRequestSearch.ts +++ b/frontend/src/hooks/api/getters/useChangeRequestSearch/useChangeRequestSearch.ts @@ -31,6 +31,12 @@ const fallbackData: ChangeRequestSearchResponseSchema = { const SWR_CACHE_SIZE = 10; const PATH = 'api/admin/search/change-requests?'; +export type SearchChangeRequestsInput = { + [K in keyof SearchChangeRequestsParams]?: + | SearchChangeRequestsParams[K] + | null; +}; + const createChangeRequestSearch = () => { const internalCache: InternalCache = {}; @@ -56,7 +62,7 @@ const createChangeRequestSearch = () => { }; return ( - params: SearchChangeRequestsParams, + params: SearchChangeRequestsInput, options: SWRConfiguration = {}, cachePrefix: string = '', ): UseChangeRequestSearchOutput => { @@ -100,11 +106,13 @@ const createChangeRequestSearch = () => { export const DEFAULT_PAGE_LIMIT = 25; -const getChangeRequestSearchFetcher = (params: SearchChangeRequestsParams) => { +const getChangeRequestSearchFetcher = (params: SearchChangeRequestsInput) => { const urlSearchParams = new URLSearchParams( Array.from( Object.entries(params) - .filter(([_, value]) => !!value) + .filter( + (param): param is [string, string | number] => !!param[1], + ) .map(([key, value]) => [key, value.toString()]), ), ).toString(); diff --git a/frontend/src/hooks/api/getters/useChangeRequests/mockChangeRequests.ts b/frontend/src/hooks/api/getters/useChangeRequests/mockChangeRequests.ts deleted file mode 100644 index 20303602ba..0000000000 --- a/frontend/src/hooks/api/getters/useChangeRequests/mockChangeRequests.ts +++ /dev/null @@ -1,448 +0,0 @@ -import type { ChangeRequestItem } from './useChangeRequests'; - -// Mock data with varied projects and change requests (expanded to 35 items for pagination testing) -export const mockChangeRequests: ChangeRequestItem[] = [ - { - id: 101, - title: 'Activate harpoons', - project: 'payment-service', - projectName: 'Payment Service', - features: ['securePaymentFlow'], - segments: [], - createdBy: { id: 1, username: 'alice', imageUrl: null }, - createdAt: '2024-01-10T10:22:00Z', - environment: 'Production', - state: 'In review', - }, - { - id: 102, - title: 'change request #102', - project: 'user-management', - projectName: 'User Management', - features: ['enhancedValidation'], - segments: [], - createdBy: { id: 2, username: 'bob', imageUrl: null }, - createdAt: '2024-01-10T08:15:00Z', - environment: 'Production', - state: 'Approved', - }, - { - id: 103, - title: 'Enable new checkout flow', - project: 'e-commerce-platform', - projectName: 'E-commerce Platform', - features: ['newCheckoutUX', 'paymentOptionsV2'], - segments: [], - createdBy: { id: 3, username: 'carol', imageUrl: null }, - createdAt: '2024-01-10T12:30:00Z', - environment: 'Testing', - state: 'In review', - }, - { - id: 104, - title: 'Update user permissions', - project: 'user-management', - projectName: 'User Management', - features: ['roleBasedAccess', 'permissionMatrix', 'adminDashboard'], - segments: [], - createdBy: { id: 4, username: 'david', imageUrl: null }, - createdAt: '2024-01-09T16:45:00Z', - environment: 'Sandbox', - state: 'In review', - }, - { - id: 105, - title: 'Deploy feature rollback', - project: 'analytics-platform', - projectName: 'Analytics Platform', - features: ['performanceTracking', 'realTimeAnalytics', 'customDashboards', 'dataExport'], - segments: [], - createdBy: { id: 5, username: 'eve', imageUrl: null }, - createdAt: '2024-01-09T14:20:00Z', - environment: 'Sandbox', - state: 'Scheduled', - schedule: { - scheduledAt: '2024-01-12T09:46:51+05:30', - status: 'Pending', - }, - }, - { - id: 106, - title: 'change request #106', - project: 'notification-service', - projectName: 'Notification Service', - features: ['emailTemplates'], - segments: [], - createdBy: { id: 6, username: 'frank', imageUrl: null }, - createdAt: '2024-01-08T11:00:00Z', - environment: 'Testing', - state: 'Approved', - }, - { - id: 107, - title: 'Optimize database queries', - project: 'data-warehouse', - projectName: 'Data Warehouse', - features: ['queryOptimization'], - segments: [], - createdBy: { id: 7, username: 'grace', imageUrl: null }, - createdAt: '2024-01-08T09:30:00Z', - environment: 'Testing', - state: 'Approved', - }, - { - id: 108, - title: 'change request #108', - project: 'mobile-app', - projectName: 'Mobile App', - features: ['pushNotifications'], - segments: [], - createdBy: { id: 8, username: 'henry', imageUrl: null }, - createdAt: '2024-01-07T15:20:00Z', - environment: 'Production', - state: 'Approved', - }, - { - id: 109, - title: 'Archive legacy features', - project: 'payment-service', - projectName: 'Payment Service', - features: ['legacyPaymentGateway'], - segments: [], - createdBy: { id: 1, username: 'alice', imageUrl: null }, - createdAt: '2024-01-07T13:10:00Z', - environment: 'Production', - state: 'Scheduled', - schedule: { - scheduledAt: '2024-01-12T09:46:51+05:30', - status: 'Failed', - reason: 'Mr Freeze', - }, - }, - // Additional 26 items to reach 35 total (ensuring >25 for pagination) - { - id: 110, - title: 'Enable dark mode', - project: 'design-system', - projectName: 'Design System', - features: ['darkTheme', 'themeToggle'], - segments: [], - createdBy: { id: 9, username: 'isabella', imageUrl: null }, - createdAt: '2024-01-06T14:30:00Z', - environment: 'Development', - state: 'Draft', - }, - { - id: 111, - title: 'API rate limiting', - project: 'api-gateway', - projectName: 'API Gateway', - features: ['rateLimiting', 'throttling'], - segments: ['premium-users'], - createdBy: { id: 10, username: 'jack', imageUrl: null }, - createdAt: '2024-01-06T10:15:00Z', - environment: 'Production', - state: 'Approved', - }, - { - id: 112, - title: 'Social media login', - project: 'auth-service', - projectName: 'Authentication Service', - features: ['googleLogin', 'facebookLogin', 'twitterLogin'], - segments: [], - createdBy: { id: 11, username: 'karen', imageUrl: null }, - createdAt: '2024-01-05T16:45:00Z', - environment: 'Testing', - state: 'In review', - }, - { - id: 113, - title: 'Real-time notifications', - project: 'notification-service', - projectName: 'Notification Service', - features: ['websocketNotifications', 'notificationCenter'], - segments: [], - createdBy: { id: 12, username: 'liam', imageUrl: null }, - createdAt: '2024-01-05T12:00:00Z', - environment: 'Development', - state: 'Draft', - }, - { - id: 114, - title: 'Multi-currency support', - project: 'payment-service', - projectName: 'Payment Service', - features: ['currencyConversion', 'multiCurrency'], - segments: ['international-users'], - createdBy: { id: 2, username: 'bob', imageUrl: null }, - createdAt: '2024-01-04T09:30:00Z', - environment: 'Sandbox', - state: 'Rejected', - }, - { - id: 115, - title: 'Advanced search filters', - project: 'e-commerce-platform', - projectName: 'E-commerce Platform', - features: ['advancedSearch', 'filterOptions', 'searchSuggestions'], - segments: [], - createdBy: { id: 13, username: 'mia', imageUrl: null }, - createdAt: '2024-01-03T14:15:00Z', - environment: 'Testing', - state: 'Applied', - }, - { - id: 116, - title: 'Machine learning recommendations', - project: 'recommendation-engine', - projectName: 'Recommendation Engine', - features: ['mlRecommendations', 'userBehaviorTracking'], - segments: ['active-users'], - createdBy: { id: 14, username: 'noah', imageUrl: null }, - createdAt: '2024-01-02T11:20:00Z', - environment: 'Development', - state: 'Draft', - }, - { - id: 117, - title: 'Video streaming optimization', - project: 'media-service', - projectName: 'Media Service', - features: ['videoOptimization', 'adaptiveBitrate'], - segments: [], - createdBy: { id: 15, username: 'olivia', imageUrl: null }, - createdAt: '2024-01-01T08:45:00Z', - environment: 'Production', - state: 'Scheduled', - schedule: { - scheduledAt: '2024-01-15T10:00:00+05:30', - status: 'Pending', - }, - }, - { - id: 118, - title: 'Inventory management system', - project: 'inventory-service', - projectName: 'Inventory Service', - features: ['stockTracking', 'lowStockAlerts', 'automaticReordering'], - segments: [], - createdBy: { id: 16, username: 'peter', imageUrl: null }, - createdAt: '2023-12-31T15:30:00Z', - environment: 'Testing', - state: 'In review', - }, - { - id: 119, - title: 'Customer support chatbot', - project: 'customer-service', - projectName: 'Customer Service', - features: ['aiChatbot', 'ticketRouting'], - segments: ['support-tier-1'], - createdBy: { id: 17, username: 'quinn', imageUrl: null }, - createdAt: '2023-12-30T13:15:00Z', - environment: 'Development', - state: 'Draft', - }, - { - id: 120, - title: 'Geolocation services', - project: 'location-service', - projectName: 'Location Service', - features: ['geoLocation', 'addressAutocomplete'], - segments: ['mobile-users'], - createdBy: { id: 18, username: 'rachel', imageUrl: null }, - createdAt: '2023-12-29T10:00:00Z', - environment: 'Sandbox', - state: 'Cancelled', - }, - { - id: 121, - title: 'Blockchain integration', - project: 'crypto-service', - projectName: 'Crypto Service', - features: ['blockchainIntegration', 'cryptoWallet'], - segments: ['crypto-users'], - createdBy: { id: 19, username: 'sam', imageUrl: null }, - createdAt: '2023-12-28T16:20:00Z', - environment: 'Development', - state: 'Draft', - }, - { - id: 122, - title: 'Voice recognition', - project: 'ai-service', - projectName: 'AI Service', - features: ['voiceRecognition', 'speechToText'], - segments: [], - createdBy: { id: 20, username: 'taylor', imageUrl: null }, - createdAt: '2023-12-27T12:45:00Z', - environment: 'Testing', - state: 'Approved', - }, - { - id: 123, - title: 'Performance monitoring', - project: 'monitoring-service', - projectName: 'Monitoring Service', - features: ['performanceMetrics', 'alerting', 'dashboards'], - segments: [], - createdBy: { id: 21, username: 'uma', imageUrl: null }, - createdAt: '2023-12-26T09:10:00Z', - environment: 'Production', - state: 'Applied', - }, - { - id: 124, - title: 'Content moderation', - project: 'content-service', - projectName: 'Content Service', - features: ['autoModeration', 'contentFiltering'], - segments: ['user-generated-content'], - createdBy: { id: 22, username: 'victor', imageUrl: null }, - createdAt: '2023-12-25T14:30:00Z', - environment: 'Testing', - state: 'In review', - }, - { - id: 125, - title: 'Email marketing automation', - project: 'marketing-service', - projectName: 'Marketing Service', - features: ['emailCampaigns', 'marketingAutomation'], - segments: ['marketing-subscribers'], - createdBy: { id: 23, username: 'wendy', imageUrl: null }, - createdAt: '2023-12-24T11:20:00Z', - environment: 'Development', - state: 'Draft', - }, - { - id: 126, - title: 'Data backup and recovery', - project: 'backup-service', - projectName: 'Backup Service', - features: ['automaticBackup', 'dataRecovery'], - segments: [], - createdBy: { id: 24, username: 'xavier', imageUrl: null }, - createdAt: '2023-12-23T08:15:00Z', - environment: 'Production', - state: 'Scheduled', - schedule: { - scheduledAt: '2024-01-20T02:00:00+05:30', - status: 'Pending', - }, - }, - { - id: 127, - title: 'Load balancing optimization', - project: 'infrastructure', - projectName: 'Infrastructure', - features: ['loadBalancer', 'trafficDistribution'], - segments: [], - createdBy: { id: 25, username: 'yara', imageUrl: null }, - createdAt: '2023-12-22T15:45:00Z', - environment: 'Production', - state: 'Approved', - }, - { - id: 128, - title: 'Calendar integration', - project: 'calendar-service', - projectName: 'Calendar Service', - features: ['calendarSync', 'eventReminders'], - segments: [], - createdBy: { id: 26, username: 'zoe', imageUrl: null }, - createdAt: '2023-12-21T13:30:00Z', - environment: 'Testing', - state: 'In review', - }, - { - id: 129, - title: 'Document collaboration', - project: 'document-service', - projectName: 'Document Service', - features: ['realTimeEditing', 'documentSharing'], - segments: ['business-users'], - createdBy: { id: 3, username: 'carol', imageUrl: null }, - createdAt: '2023-12-20T10:15:00Z', - environment: 'Development', - state: 'Draft', - }, - { - id: 130, - title: 'Mobile app security', - project: 'mobile-app', - projectName: 'Mobile App', - features: ['biometricAuth', 'appSecurityScanning'], - segments: ['mobile-users'], - createdBy: { id: 27, username: 'adam', imageUrl: null }, - createdAt: '2023-12-19T16:00:00Z', - environment: 'Testing', - state: 'Approved', - }, - { - id: 131, - title: 'Analytics dashboard v2', - project: 'analytics-platform', - projectName: 'Analytics Platform', - features: ['advancedDashboard', 'customCharts', 'dataVisualization'], - segments: ['analytics-users'], - createdBy: { id: 5, username: 'eve', imageUrl: null }, - createdAt: '2023-12-18T12:20:00Z', - environment: 'Development', - state: 'In review', - }, - { - id: 132, - title: 'Microservices migration', - project: 'architecture', - projectName: 'Architecture', - features: ['microservicesArchitecture', 'serviceDecomposition'], - segments: [], - createdBy: { id: 28, username: 'blake', imageUrl: null }, - createdAt: '2023-12-17T09:45:00Z', - environment: 'Development', - state: 'Draft', - }, - { - id: 133, - title: 'API versioning strategy', - project: 'api-gateway', - projectName: 'API Gateway', - features: ['apiVersioning', 'backwardCompatibility'], - segments: ['api-consumers'], - createdBy: { id: 10, username: 'jack', imageUrl: null }, - createdAt: '2023-12-16T14:10:00Z', - environment: 'Testing', - state: 'Applied', - }, - { - id: 134, - title: 'User onboarding flow', - project: 'user-management', - projectName: 'User Management', - features: ['onboardingWizard', 'userTutorials'], - segments: ['new-users'], - createdBy: { id: 29, username: 'claire', imageUrl: null }, - createdAt: '2023-12-15T11:35:00Z', - environment: 'Production', - state: 'Scheduled', - schedule: { - scheduledAt: '2024-01-25T09:00:00+05:30', - status: 'Suspended', - reason: 'Resource constraints', - }, - }, - { - id: 135, - title: 'Feature flag management', - project: 'feature-management', - projectName: 'Feature Management', - features: ['featureFlags', 'gradualRollout'], - segments: ['beta-testers'], - createdBy: { id: 30, username: 'derek', imageUrl: null }, - createdAt: '2023-12-14T08:25:00Z', - environment: 'Production', - state: 'Approved', - }, -]; \ No newline at end of file diff --git a/frontend/src/hooks/api/getters/useChangeRequests/useChangeRequests.ts b/frontend/src/hooks/api/getters/useChangeRequests/useChangeRequests.ts deleted file mode 100644 index 3e4daa9e50..0000000000 --- a/frontend/src/hooks/api/getters/useChangeRequests/useChangeRequests.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { useMemo } from 'react'; -import { createPaginatedHook } from '../usePaginatedData/usePaginatedData.js'; -import { mockChangeRequests } from './mockChangeRequests.js'; - -// Type for change request data based on schema -export interface ChangeRequestItem { - id: number; - title: string; - environment: string; - project: string; - projectName?: string; // Not in schema but used by GlobalChangeRequestTitleCell - createdBy: { - id: number; - username?: string | null; - imageUrl?: string | null; - }; - createdAt: string; - features: string[]; - segments: string[]; - state: 'Draft' | 'Approved' | 'In review' | 'Applied' | 'Scheduled' | 'Rejected' | 'Cancelled'; - schedule?: { - scheduledAt: string; - status: 'Pending' | 'Failed' | 'Suspended'; - reason?: string; - }; -} - -export interface ChangeRequestsResponse { - changeRequests: ChangeRequestItem[]; - total: number; -} - - -// Sort function that mimics server-side sorting -const sortData = (data: ChangeRequestItem[], sortBy: string, sortOrder: string) => { - return [...data].sort((a, b) => { - let aValue: any; - let bValue: any; - - switch (sortBy) { - case 'title': - aValue = a.title.toLowerCase(); - bValue = b.title.toLowerCase(); - break; - case 'createdAt': - aValue = new Date(a.createdAt).getTime(); - bValue = new Date(b.createdAt).getTime(); - break; - case 'environment': - aValue = a.environment.toLowerCase(); - bValue = b.environment.toLowerCase(); - break; - case 'state': - aValue = a.state.toLowerCase(); - bValue = b.state.toLowerCase(); - break; - case 'createdBy': - aValue = a.createdBy.username?.toLowerCase() || ''; - bValue = b.createdBy.username?.toLowerCase() || ''; - break; - default: - return 0; - } - - if (aValue < bValue) { - return sortOrder === 'asc' ? -1 : 1; - } - if (aValue > bValue) { - return sortOrder === 'asc' ? 1 : -1; - } - return 0; - }); -}; - -// Pagination function -const paginateData = (data: ChangeRequestItem[], offset: number, limit: number) => { - return data.slice(offset, offset + limit); -}; - -// Create the hook using the established pattern but with custom mock logic -export const useChangeRequests = createPaginatedHook( - { changeRequests: [], total: 0 }, - '', // No API endpoint - we'll override the fetcher -); - -// Override the created hook to add custom mock data logic -const originalUseChangeRequests = useChangeRequests; -export const useChangeRequestsWithMockData = ( - params: Record = {}, - dynamicPrefixKey: string = '', - options: any = {}, -) => { - // Extract parameters with defaults - const offset = Number(params?.offset) || 0; - const limit = Number(params?.limit) || 25; - const sortBy = params?.sortBy || 'createdAt'; - const sortOrder = params?.sortOrder || 'desc'; - - const mockData = useMemo(() => { - // Apply sorting (simulating server-side sorting) - const sortedData = sortData(mockChangeRequests, sortBy, sortOrder); - - // Apply pagination (simulating server-side pagination) - const paginatedData = paginateData(sortedData, offset, limit); - - return { - changeRequests: paginatedData, - total: mockChangeRequests.length, - }; - }, [offset, limit, sortBy, sortOrder]); - - // Simulate loading and return mock data - return { - ...mockData, - loading: false, - initialLoad: false, - error: null, - }; -}; - -// For now, use the mock version. Later, replace with the real API version -export { useChangeRequestsWithMockData as useChangeRequestsSearch }; \ No newline at end of file