This commit is contained in:
chamikaJ
2025-04-17 18:28:54 +05:30
parent f583291d8a
commit 8825b0410a
2837 changed files with 241385 additions and 127578 deletions

View File

@@ -0,0 +1,113 @@
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import { ITaskLabel } from '@/types/tasks/taskLabel.types';
import logger from '@utils/errorLogger';
import { labelsApiService } from '@/api/taskAttributes/labels/labels.api.service';
interface ILabelState {
labels: ITaskLabel[];
selectedLabel: ITaskLabel | null;
loading: boolean;
error: string | null;
initialized: boolean;
}
const initialState: ILabelState = {
labels: [],
selectedLabel: null,
loading: false,
error: null,
initialized: false,
};
// Create async thunk for fetching labels
export const fetchLabels = createAsyncThunk(
'taskLabel/fetchLabels',
async (_, { rejectWithValue }) => {
try {
const response = await labelsApiService.getLabels();
return response.body;
} catch (error) {
logger.error('Fetch Labels', error);
if (error instanceof Error) {
return rejectWithValue(error.message);
}
return rejectWithValue('Failed to fetch labels');
}
}
);
// Create async thunk for fetching labels by task
export const fetchLabelsByTask = createAsyncThunk(
'taskLabel/fetchLabelsByTask',
async (taskId: string, { rejectWithValue }) => {
try {
const response = await labelsApiService.getPriorityByTask(taskId);
return response.body;
} catch (error) {
logger.error('Fetch Labels By Task', error);
if (error instanceof Error) {
return rejectWithValue(error.message);
}
return rejectWithValue('Failed to fetch task labels');
}
}
);
// Initialization thunk
export const initializeLabels = createAsyncThunk(
'taskLabel/initialize',
async (_, { dispatch, getState }) => {
const state = getState() as { taskLabelReducer: ILabelState };
if (!state.taskLabelReducer.initialized) {
await dispatch(fetchLabels());
}
}
);
const taskLabelSlice = createSlice({
name: 'taskLabelReducer',
initialState,
reducers: {
updateLabelColor: (state, action: PayloadAction<{ id: string; color: string }>) => {
const label = state.labels.find(l => l.id === action.payload.id);
if (label) {
label.color_code = action.payload.color;
}
},
deleteLabel: (state, action: PayloadAction<string>) => {
state.labels = state.labels.filter(label => label.id !== action.payload);
},
},
extraReducers: builder => {
builder
.addCase(fetchLabels.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(fetchLabels.fulfilled, (state, action: PayloadAction<ITaskLabel[]>) => {
state.loading = false;
state.labels = action.payload;
state.initialized = true;
})
.addCase(fetchLabels.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
})
// Fetch Labels By Task
.addCase(fetchLabelsByTask.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(fetchLabelsByTask.fulfilled, (state, action: PayloadAction<ITaskLabel[]>) => {
state.loading = false;
state.labels = action.payload;
})
.addCase(fetchLabelsByTask.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
});
},
});
export const { updateLabelColor, deleteLabel } = taskLabelSlice.actions;
export default taskLabelSlice.reducer;

View File

@@ -0,0 +1,85 @@
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
export interface ITeamMember {
id?: string;
name?: string;
job_title_id?: string;
is_owner?: boolean;
user_id?: string;
team_id?: string;
pending_invitation?: boolean;
role_id?: string;
created_at?: string;
updated_at?: string;
}
export interface ITeamMemberViewModel extends ITeamMember {
id?: string;
active?: boolean;
name?: string;
taskCount?: number;
job_title?: string;
email?: string;
task_count?: number;
projects_count?: number;
role_name?: string;
tasks?: any[]; // ITask[] type would need to be imported
is_admin?: boolean;
show_handles?: boolean;
is_online?: boolean;
avatar_url?: string;
selected?: boolean;
color_code?: string;
usage?: number;
projects?: any;
total_logged_time?: string;
member_teams?: string[];
is_pending?: boolean;
}
interface TaskMemberState {
assignees: ITeamMemberViewModel[];
loading: boolean;
error: string | null;
}
const initialState: TaskMemberState = {
assignees: [],
loading: false,
error: null,
};
export const fetchTaskAssignees = createAsyncThunk(
'taskMember/fetchTaskAssignees',
async (projectId: string) => {
const response = await fetch(`/api/tasks/assignees/${projectId}`);
const data = await response.json();
return data.data;
}
);
const taskMemberSlice = createSlice({
name: 'taskMember',
initialState,
reducers: {},
extraReducers: builder => {
builder
.addCase(fetchTaskAssignees.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(
fetchTaskAssignees.fulfilled,
(state, action: PayloadAction<ITeamMemberViewModel[]>) => {
state.loading = false;
state.assignees = action.payload;
}
)
.addCase(fetchTaskAssignees.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message || 'Failed to fetch assignees';
});
},
});
export default taskMemberSlice.reducer;

View File

@@ -0,0 +1,105 @@
import { priorityApiService } from '@/api/taskAttributes/priority/priority.api.service';
import { ITaskPrioritiesGetResponse, ITaskPriority } from '@/types/tasks/taskPriority.types';
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import logger from '@utils/errorLogger';
interface ITaskPriorityState {
priorities: ITaskPrioritiesGetResponse[];
selectedPriority: ITaskPriority | null;
loading: boolean;
error: string | null;
initialized: boolean;
}
const initialState: ITaskPriorityState = {
priorities: [],
selectedPriority: null,
loading: false,
error: null,
initialized: false,
};
// Create async thunk for fetching priorities
export const fetchPriorities = createAsyncThunk(
'taskPriority/fetchPriorities',
async (_, { rejectWithValue }) => {
try {
const response = await priorityApiService.getPriorities();
return response.body;
} catch (error) {
logger.error('Fetch Priorities', error);
if (error instanceof Error) {
return rejectWithValue(error.message);
}
return rejectWithValue('Failed to fetch priorities');
}
}
);
// Create async thunk for fetching priority by ID
export const fetchPriorityById = createAsyncThunk(
'taskPriority/fetchPriorityById',
async (priorityId: string, { rejectWithValue }) => {
try {
const response = await priorityApiService.getPriorityById(priorityId);
return response.body;
} catch (error) {
logger.error('Fetch Priority By Id', error);
if (error instanceof Error) {
return rejectWithValue(error.message);
}
return rejectWithValue('Failed to fetch priority');
}
}
);
// Initialization thunk
export const initializePriorities = createAsyncThunk(
'taskPriority/initialize',
async (_, { dispatch, getState }) => {
const state = getState() as { taskPriorityReducer: ITaskPriorityState };
if (!state.taskPriorityReducer.initialized) {
await dispatch(fetchPriorities());
}
}
);
const taskPrioritySlice = createSlice({
name: 'taskPriorityReducer',
initialState,
reducers: {},
extraReducers: builder => {
builder
.addCase(fetchPriorities.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(
fetchPriorities.fulfilled,
(state, action: PayloadAction<ITaskPrioritiesGetResponse[]>) => {
state.loading = false;
state.priorities = action.payload;
state.initialized = true;
}
)
.addCase(fetchPriorities.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
})
// Fetch Priority By Id
.addCase(fetchPriorityById.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(fetchPriorityById.fulfilled, (state, action: PayloadAction<ITaskPriority>) => {
state.loading = false;
state.selectedPriority = action.payload;
})
.addCase(fetchPriorityById.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
});
},
});
export default taskPrioritySlice.reducer;

View File

@@ -0,0 +1,130 @@
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import { ICategorizedStatus, ITaskStatus } from '@/types/tasks/taskStatus.types';
import logger from '@utils/errorLogger';
import { statusApiService } from '@/api/taskAttributes/status/status.api.service';
import { ITaskStatusCategory } from '@/types/status.types';
import { ITaskStatusCreateRequest } from '@/types/tasks/task-status-create-request';
interface IStatusState {
status: ITaskStatus[];
statusCategories: ITaskStatusCategory[];
loading: boolean;
error: string | null;
initialized: boolean;
}
const initialState: IStatusState = {
status: [],
statusCategories: [],
loading: false,
error: null,
initialized: false,
};
// Create async thunk for fetching statuses
export const fetchStatuses = createAsyncThunk(
'status/fetchStatuses',
async (projectId: string, { rejectWithValue }) => {
try {
const response = await statusApiService.getStatuses(projectId);
return response.body;
} catch (error) {
logger.error('Fetch Statuses', error);
if (error instanceof Error) {
return rejectWithValue(error.message);
}
return rejectWithValue('Failed to fetch statuses');
}
}
);
export const fetchStatusesCategories = createAsyncThunk(
'status/fetchStatusesCategories',
async (_, { rejectWithValue }) => {
try {
const response = await statusApiService.getStatusCategories();
return response.body;
} catch (error) {
logger.error('Fetch Statuses Categories', error);
if (error instanceof Error) {
return rejectWithValue(error.message);
}
return rejectWithValue('Failed to fetch statuses categories');
}
}
);
export const createStatus = createAsyncThunk(
'status/createStatus',
async (
{ body, currentProjectId }: { body: ITaskStatusCreateRequest; currentProjectId: string },
{ rejectWithValue }
) => {
return await statusApiService.createStatus(body, currentProjectId);
}
);
const taskStatusSlice = createSlice({
name: 'taskStatusReducer',
initialState,
reducers: {
addStatus: (state, action: PayloadAction<ITaskStatus>) => {
state.status.push(action.payload);
},
updateStatus: (state, action: PayloadAction<ITaskStatus>) => {
const index = state.status.findIndex(status => status.id === action.payload.id);
if (index !== -1) {
state.status[index] = action.payload;
}
},
deleteStatus: (state, action: PayloadAction<string>) => {
state.status = state.status.filter(status => status.id !== action.payload);
},
setCategorizedStatuses: (state, action: PayloadAction<ITaskStatusCategory[]>) => {
state.statusCategories = action.payload;
},
resetStatuses: state => {
state.status = [];
state.loading = false;
state.error = null;
state.initialized = false;
},
},
extraReducers: builder => {
builder
.addCase(fetchStatuses.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(fetchStatuses.fulfilled, (state, action: PayloadAction<ITaskStatus[]>) => {
state.loading = false;
state.status = action.payload;
state.initialized = true;
state.error = null;
})
.addCase(fetchStatuses.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
})
.addCase(fetchStatusesCategories.pending, state => {
state.loading = true;
state.error = null;
})
.addCase(
fetchStatusesCategories.fulfilled,
(state, action: PayloadAction<ITaskStatusCategory[]>) => {
state.loading = false;
state.statusCategories = action.payload;
state.error = null;
}
)
.addCase(fetchStatusesCategories.rejected, (state, action) => {
state.loading = false;
state.error = action.payload as string;
});
},
});
export const { addStatus, updateStatus, deleteStatus, setCategorizedStatuses, resetStatuses } =
taskStatusSlice.actions;
export default taskStatusSlice.reducer;