mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-01-13 05:09:51 -06:00
Initial commit
This commit is contained in:
@@ -8,6 +8,8 @@ import EmailTextField from "../../TextFields/Email/EmailTextField";
|
||||
import StringTextField from "../../TextFields/Text/TextField";
|
||||
import Avatar from "../../Avatar";
|
||||
import { editProfileValidation } from "../../../Validation/validation";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { update } from "../../../Features/Auth/authSlice";
|
||||
|
||||
/**
|
||||
* ProfilePanel component displays a form for editing user profile information
|
||||
@@ -19,22 +21,24 @@ import { editProfileValidation } from "../../../Validation/validation";
|
||||
|
||||
const ProfilePanel = () => {
|
||||
const theme = useTheme();
|
||||
//TODO - use redux loading state
|
||||
//!! - currently all loading buttons are tied to the same state
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
//for testing, will tweak when I implement redux slice
|
||||
const { user, isLoading } = useSelector((state) => state.auth);
|
||||
console.log(user);
|
||||
const idToName = {
|
||||
"edit-first-name": "firstname",
|
||||
"edit-last-name": "lastname",
|
||||
"edit-email": "email",
|
||||
};
|
||||
const [localData, setLocalData] = useState({
|
||||
firstname: "",
|
||||
lastname: "",
|
||||
email: "",
|
||||
firstname: user.firstname,
|
||||
lastname: user.lastname,
|
||||
email: user.email,
|
||||
profilePicUrl: ""
|
||||
});
|
||||
const [errors, setErrors] = useState({});
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [loadingPfp, setLoadingPfp] = useState(false);
|
||||
|
||||
const handleChange = (event) => {
|
||||
const { value, id } = event.target;
|
||||
@@ -43,7 +47,7 @@ const ProfilePanel = () => {
|
||||
...prev,
|
||||
[name]: value,
|
||||
}));
|
||||
|
||||
|
||||
const validation = editProfileValidation.validate(
|
||||
{ [name]: value },
|
||||
{ abortEarly: false }
|
||||
@@ -63,29 +67,19 @@ const ProfilePanel = () => {
|
||||
|
||||
//TODO - implement delete profile picture function
|
||||
const handleDeletePicture = () => {
|
||||
setIsLoading(true);
|
||||
setLoadingPfp(true);
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
setLoadingPfp(false);
|
||||
}, 2000);
|
||||
};
|
||||
//TODO - implement update profile function
|
||||
const handleUpdatePicture = () => {};
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
//TODO - implement delete account function
|
||||
const handleDeleteAccount = () => {
|
||||
setIsLoading(true);
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
setIsOpen(false);
|
||||
}, 2000);
|
||||
};
|
||||
const handleDeleteAccount = () => {};
|
||||
//TODO - implement save profile function
|
||||
const handleSaveProfile = () => {
|
||||
setIsLoading(true);
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
setIsOpen(false);
|
||||
}, 2000);
|
||||
const handleSaveProfile = (event) => {
|
||||
event.preventDefault();
|
||||
dispatch(update(user._id, localData));
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -101,6 +95,7 @@ const ProfilePanel = () => {
|
||||
<StringTextField
|
||||
id="edit-first-name"
|
||||
label={null}
|
||||
value={localData.firstname}
|
||||
placeholder="Enter your first name"
|
||||
autoComplete="given-name"
|
||||
onChange={handleChange}
|
||||
@@ -125,6 +120,7 @@ const ProfilePanel = () => {
|
||||
<StringTextField
|
||||
id="edit-last-name"
|
||||
label={null}
|
||||
value={localData.lastname}
|
||||
placeholder="Enter your last name"
|
||||
autoComplete="family-name"
|
||||
onChange={handleChange}
|
||||
@@ -152,6 +148,7 @@ const ProfilePanel = () => {
|
||||
<EmailTextField
|
||||
id="edit-email"
|
||||
label={null}
|
||||
value={localData.email}
|
||||
placeholder="Enter your email"
|
||||
autoComplete="email"
|
||||
onChange={handleChange}
|
||||
@@ -179,8 +176,8 @@ const ProfilePanel = () => {
|
||||
{/* TODO - Update placeholder values with redux data */}
|
||||
<Avatar
|
||||
src="/static/images/avatar/2.jpg"
|
||||
firstName="Jackie"
|
||||
lastName="Dawn"
|
||||
firstName={localData.firstname}
|
||||
lastName={localData.lastname}
|
||||
sx={{
|
||||
width: "64px",
|
||||
height: "64px",
|
||||
@@ -192,7 +189,7 @@ const ProfilePanel = () => {
|
||||
level="tertiary"
|
||||
label="Delete"
|
||||
onClick={handleDeletePicture}
|
||||
isLoading={isLoading}
|
||||
isLoading={loadingPfp}
|
||||
/>
|
||||
{/* TODO - modal popup for update pfp? */}
|
||||
<Button
|
||||
@@ -217,7 +214,7 @@ const ProfilePanel = () => {
|
||||
level="primary"
|
||||
label="Save"
|
||||
onClick={handleSaveProfile}
|
||||
isLoading={isLoading}
|
||||
isLoading={false}
|
||||
loadingText="Saving..."
|
||||
disabled={Object.keys(errors).length !== 0 && true}
|
||||
sx={{
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useTheme } from "@mui/material";
|
||||
* @param {function} props.onChange - The function to call when the text field changes.
|
||||
* @param {string} props.id - The id of the text field.
|
||||
* @param {string} [props.label="Email"] - The label of the text field.
|
||||
* @param {string} props.value - The value of the text field.
|
||||
* @param {string} props.variant - The variant of the text field.
|
||||
* @param {string} props.placeholder - The placeholder of the text field.
|
||||
* @param {React.Element} props.icon - The icon to be displayed in the text field.
|
||||
@@ -30,6 +31,7 @@ const EmailTextField = ({
|
||||
onChange,
|
||||
id,
|
||||
label = "Email",
|
||||
value = undefined,
|
||||
variant,
|
||||
placeholder,
|
||||
autoComplete,
|
||||
@@ -59,6 +61,7 @@ const EmailTextField = ({
|
||||
error={error}
|
||||
className="email-text-field-input"
|
||||
id={id}
|
||||
value={value}
|
||||
variant={variant}
|
||||
placeholder={placeholder}
|
||||
autoComplete={autoComplete}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useTheme } from "@mui/material";
|
||||
* @param {function} props.onChange - The function to call when the text field changes.
|
||||
* @param {string} props.id - The ID of the text field.
|
||||
* @param {string} props.label - The label text for the text field.
|
||||
* @param {string} props.value - The value of the text field.
|
||||
* @param {string} props.variant - The variant of the text field.
|
||||
* @param {string} props.placeholder - The placeholder text for the text field.
|
||||
* @param {ReactNode} props.icon - The icon to display in the text field.
|
||||
@@ -22,6 +23,7 @@ const StringTextField = ({
|
||||
autoComplete,
|
||||
id,
|
||||
label,
|
||||
value = undefined,
|
||||
variant,
|
||||
placeholder,
|
||||
icon,
|
||||
@@ -51,6 +53,7 @@ const StringTextField = ({
|
||||
className="email-text-field-input"
|
||||
id={id}
|
||||
variant={variant}
|
||||
value={value}
|
||||
placeholder={placeholder}
|
||||
autoComplete={autoComplete}
|
||||
InputProps={{
|
||||
|
||||
@@ -32,6 +32,28 @@ export const login = createAsyncThunk("auth/login", async (form, thunkApi) => {
|
||||
}
|
||||
});
|
||||
|
||||
export const update = createAsyncThunk(
|
||||
"auth/update",
|
||||
async (user_id, form, thunkApi) => {
|
||||
try {
|
||||
const res = await axios.post(`${BASE_URL}/auth/user/${user_id}`, form);
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return thunkApi.rejectWithValue(error.response.data);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const deleteAccount = createAsyncThunk(
|
||||
"auth/delete",
|
||||
async (form, thunkApi) => {
|
||||
try {
|
||||
//TODO
|
||||
} catch (error) {}
|
||||
}
|
||||
);
|
||||
|
||||
const handleAuthFulfilled = (state, action) => {
|
||||
state.isLoading = false;
|
||||
state.success = action.payload.success;
|
||||
@@ -72,7 +94,13 @@ const authSlice = createSlice({
|
||||
state.isLoading = true;
|
||||
})
|
||||
.addCase(login.fulfilled, handleAuthFulfilled)
|
||||
.addCase(login.rejected, handleAuthRejected);
|
||||
.addCase(login.rejected, handleAuthRejected)
|
||||
// Update thunk
|
||||
.addCase(update.pending, (state) => {
|
||||
state.isLoading = true;
|
||||
})
|
||||
.addCase(update.fulfilled, handleAuthFulfilled)
|
||||
.addCase(update.rejected, handleAuthRejected);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
.announcement-tile {
|
||||
border-color: var(--env-var-color-29);
|
||||
}
|
||||
[class$="-form"] {
|
||||
.settings [class$="-form"] {
|
||||
width: inherit;
|
||||
}
|
||||
[class$="__wrapper"],
|
||||
[class$="__wrapper compact"] {
|
||||
.settings [class$="__wrapper"],
|
||||
.settings [class$="__wrapper compact"] {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
Reference in New Issue
Block a user