mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-01-07 18:29:41 -06:00
add redux state for settings
This commit is contained in:
119
Client/src/Features/Settings/settingsSlice.js
Normal file
119
Client/src/Features/Settings/settingsSlice.js
Normal file
@@ -0,0 +1,119 @@
|
||||
import { networkService } from "../../main";
|
||||
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
import axios from "axios";
|
||||
|
||||
const initialState = {
|
||||
isLoading: false,
|
||||
apiBaseUrl: "http://localhost:5000/api/v1",
|
||||
logLevel: "debug",
|
||||
clientHost: "http://localhost:5173",
|
||||
jwtSecret: "my_secret",
|
||||
dbType: "MongoDB",
|
||||
dbConnectionString: "mongodb://localhost:27017/uptime_db",
|
||||
redisHost: "127.0.0.1",
|
||||
redisPort: 6379,
|
||||
jwtTTL: "99d",
|
||||
pagespeedApiKey: "",
|
||||
systemEmailHost: "smtp.gmail.com",
|
||||
systemEmailPort: 465,
|
||||
systemEmailAddress: "",
|
||||
systemEmailPassword: "",
|
||||
};
|
||||
|
||||
export const getAppSettings = createAsyncThunk(
|
||||
"settings/getSettings",
|
||||
async (data, thunkApi) => {
|
||||
try {
|
||||
const res = await networkService.getAppSettings({
|
||||
authToken: data.authToken,
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
if (error.response.data) {
|
||||
return thunkApi.rejectWithValue(error.response.data);
|
||||
}
|
||||
const payload = {
|
||||
status: false,
|
||||
msg: error.message ? error.message : "Unknown error",
|
||||
};
|
||||
return thunkApi.rejectWithValue(payload);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const updateAppSettings = createAsyncThunk(
|
||||
"settings/updateSettings",
|
||||
async (form, thunkApi) => {
|
||||
try {
|
||||
const res = await networkService.loginUser(form);
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) {
|
||||
return thunkApi.rejectWithValue(error.response.data);
|
||||
}
|
||||
const payload = {
|
||||
status: false,
|
||||
msg: error.message ? error.message : "Unknown error",
|
||||
};
|
||||
return thunkApi.rejectWithValue(payload);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const handleGetSettingsFulfilled = (state, action) => {
|
||||
state.isLoading = false;
|
||||
state.success = action.payload.success;
|
||||
state.msg = action.payload.msg;
|
||||
};
|
||||
const handleGetSettingsRejected = (state, action) => {
|
||||
state.isLoading = false;
|
||||
state.success = false;
|
||||
state.msg = action.payload ? action.payload.msg : "Failed to get settings.";
|
||||
};
|
||||
const handleUpdateSettingsFulfilled = (state, action) => {
|
||||
state.isLoading = false;
|
||||
state.success = action.payload.success;
|
||||
state.msg = action.payload.msg;
|
||||
};
|
||||
const handleUpdateSettingsRejected = (state, action) => {
|
||||
state.isLoading = false;
|
||||
state.success = false;
|
||||
state.msg = action.payload
|
||||
? action.payload.msg
|
||||
: "Failed to update settings.";
|
||||
};
|
||||
|
||||
const settingsSlice = createSlice({
|
||||
name: "settings",
|
||||
initialState,
|
||||
reducers: {
|
||||
clearAuthState: (state) => {
|
||||
state.authToken = "";
|
||||
state.user = "";
|
||||
state.isLoading = false;
|
||||
state.success = true;
|
||||
state.msg = "Logged out successfully";
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
// Register thunk
|
||||
builder
|
||||
.addCase(getAppSettings.pending, (state) => {
|
||||
state.isLoading = true;
|
||||
})
|
||||
.addCase(getAppSettings.fulfilled, handleGetSettingsFulfilled)
|
||||
.addCase(getAppSettings.rejected, handleGetSettingsRejected);
|
||||
|
||||
// Login thunk
|
||||
builder
|
||||
.addCase(updateAppSettings.pending, (state) => {
|
||||
state.isLoading = true;
|
||||
})
|
||||
.addCase(updateAppSettings.fulfilled, handleUpdateSettingsFulfilled)
|
||||
.addCase(updateAppSettings.rejected, handleUpdateSettingsRejected);
|
||||
},
|
||||
});
|
||||
|
||||
export default settingsSlice.reducer;
|
||||
export const { clearAuthState } = settingsSlice.actions;
|
||||
@@ -13,11 +13,12 @@ import {
|
||||
deleteAllMonitors,
|
||||
} from "../../Features/UptimeMonitors/uptimeMonitorsSlice";
|
||||
import { update } from "../../Features/Auth/authSlice";
|
||||
import { getAppSettings } from "../../Features/Settings/settingsSlice";
|
||||
import PropTypes from "prop-types";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import { setTimezone } from "../../Features/UI/uiSlice";
|
||||
import timezones from "../../Utils/timezones.json";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ConfigBox } from "./styled";
|
||||
import { networkService } from "../../main";
|
||||
import { settingsValidation } from "../../Validation/validation";
|
||||
@@ -35,9 +36,25 @@ const Settings = ({ isAdmin }) => {
|
||||
const [form, setForm] = useState({
|
||||
ttl: checkTTL ? (checkTTL / SECONDS_PER_DAY).toString() : 0,
|
||||
});
|
||||
const [settings, setSettings] = useState({
|
||||
apiBaseUrl: "",
|
||||
});
|
||||
const [errors, setErrors] = useState({});
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchSettings = async () => {
|
||||
const action = await dispatch(getAppSettings({ authToken }));
|
||||
if (getAppSettings.fulfilled.match(action)) {
|
||||
const settings = action.payload.data;
|
||||
setSettings(settings);
|
||||
} else if (getAppSettings.rejected.match(action)) {
|
||||
throw new Error(action.error.message);
|
||||
}
|
||||
};
|
||||
fetchSettings();
|
||||
}, [dispatch, authToken]);
|
||||
|
||||
const handleChange = (event) => {
|
||||
const { value, id } = event.target;
|
||||
const { error } = settingsValidation.validate(
|
||||
@@ -249,6 +266,23 @@ const Settings = ({ isAdmin }) => {
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
)}
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h1">Client Settings</Typography>
|
||||
<Typography sx={{ mt: theme.spacing(2) }}>
|
||||
Here you can modify settings for the client.
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.spacing(20)}>
|
||||
<Field
|
||||
id="apiBaseUrl"
|
||||
label="Base URL for backend API"
|
||||
value={settings.apiBaseUrl}
|
||||
onChange={handleChange}
|
||||
error={errors["settings-client-base-url"]}
|
||||
/>
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h1">About</Typography>
|
||||
|
||||
@@ -619,6 +619,27 @@ class NetworkService {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* ************************************
|
||||
* Get app settings
|
||||
* ************************************
|
||||
*
|
||||
* @async
|
||||
* @param {Object} config - The configuration object.
|
||||
* @param {string} config.authToken - The authorization token to be used in the request header.
|
||||
* @returns {Promise<AxiosResponse>} The response from the axios GET request.
|
||||
*
|
||||
*/
|
||||
|
||||
async getAppSettings(config) {
|
||||
return this.axiosInstance.get("/settings", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${config.authToken}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default NetworkService;
|
||||
|
||||
Reference in New Issue
Block a user