Skip to content

Commit 0bbc278

Browse files
fix(profile): prevent saving profile when no changes are made
1 parent 841dbe3 commit 0bbc278

2 files changed

Lines changed: 66 additions & 21 deletions

File tree

frontend/src/styles/inputs.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ input[type="checkbox"] {
114114
position: relative;
115115
transition: background 0.125s;
116116
flex-shrink: 0;
117+
cursor: pointer;
117118
&:after {
118119
font-family: "Font Awesome";
119120
content: "\f00c";

frontend/src/ts/modals/edit-profile.ts

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export function show(): void {
2323
void modal.show({
2424
beforeAnimation: async () => {
2525
hydrateInputs();
26+
originalState = getProfileState();
2627
initializeCharacterCounters();
2728
},
2829
});
@@ -105,40 +106,83 @@ function hydrateInputs(): void {
105106
indicators.forEach((it) => it.hide());
106107
}
107108

109+
let characterCountersInitialized = false;
110+
108111
function initializeCharacterCounters(): void {
112+
if (characterCountersInitialized) return;
109113
new CharacterCounter(bioInput, 250);
110114
new CharacterCounter(keyboardInput, 75);
115+
characterCountersInitialized = true;
111116
}
112117

113-
function buildUpdatesFromInputs(): UserProfileDetails {
114-
const bio = bioInput.getValue() ?? "";
115-
const keyboard = keyboardInput.getValue() ?? "";
116-
const twitter = twitterInput.getValue() ?? "";
117-
const github = githubInput.getValue() ?? "";
118-
const website = websiteInput.getValue() ?? "";
119-
const showActivityOnPublicProfile =
120-
showActivityOnPublicProfileInput.isChecked() ?? false;
121-
122-
const profileUpdates: UserProfileDetails = {
123-
bio,
124-
keyboard,
118+
type ProfileState = {
119+
bio: string;
120+
keyboard: string;
121+
twitter: string;
122+
github: string;
123+
website: string;
124+
badgeId: number;
125+
showActivityOnPublicProfile: boolean;
126+
};
127+
128+
function getProfileState(): ProfileState {
129+
return {
130+
bio: bioInput.getValue() ?? "",
131+
keyboard: keyboardInput.getValue() ?? "",
132+
twitter: twitterInput.getValue() ?? "",
133+
github: githubInput.getValue() ?? "",
134+
website: websiteInput.getValue() ?? "",
135+
badgeId: currentSelectedBadgeId,
136+
showActivityOnPublicProfile:
137+
showActivityOnPublicProfileInput.isChecked() ?? false,
138+
};
139+
}
140+
141+
function buildUpdatesFromState(state: ProfileState): UserProfileDetails {
142+
return {
143+
bio: state.bio,
144+
keyboard: state.keyboard,
125145
socialProfiles: {
126-
twitter,
127-
github,
128-
website,
146+
twitter: state.twitter,
147+
github: state.github,
148+
website: state.website,
129149
},
130-
showActivityOnPublicProfile,
150+
showActivityOnPublicProfile: state.showActivityOnPublicProfile,
131151
};
152+
}
153+
154+
let originalState: ProfileState | null = null;
132155

133-
return profileUpdates;
156+
function hasProfileChanged(
157+
originalState: ProfileState | null,
158+
currentState: ProfileState,
159+
): boolean {
160+
if (originalState === null) return true;
161+
162+
return (
163+
originalState.bio !== currentState.bio ||
164+
originalState.keyboard !== currentState.keyboard ||
165+
originalState.twitter !== currentState.twitter ||
166+
originalState.github !== currentState.github ||
167+
originalState.website !== currentState.website ||
168+
originalState.badgeId !== currentState.badgeId ||
169+
originalState.showActivityOnPublicProfile !==
170+
currentState.showActivityOnPublicProfile
171+
);
134172
}
135173

136174
async function updateProfile(): Promise<void> {
137175
const snapshot = DB.getSnapshot();
138176
if (!snapshot) return;
139-
const updates = buildUpdatesFromInputs();
140177

141-
// check for length resctrictions before sending server requests
178+
const currentState = getProfileState();
179+
if (!hasProfileChanged(originalState, currentState)) {
180+
showErrorNotification("No changes to save");
181+
return;
182+
}
183+
184+
const updates = buildUpdatesFromState(currentState);
185+
// check for length restrictions before sending server requests
142186
const githubLengthLimit = 39;
143187
if (
144188
updates.socialProfiles?.github !== undefined &&
@@ -176,7 +220,7 @@ async function updateProfile(): Promise<void> {
176220
}
177221

178222
snapshot.details = response.body.data ?? updates;
179-
snapshot.inventory?.badges.forEach((badge) => {
223+
snapshot.inventory?.badges?.forEach((badge) => {
180224
if (badge.id === currentSelectedBadgeId) {
181225
badge.selected = true;
182226
} else {
@@ -185,7 +229,7 @@ async function updateProfile(): Promise<void> {
185229
});
186230

187231
DB.setSnapshot(snapshot);
188-
232+
originalState = currentState;
189233
showSuccessNotification("Profile updated");
190234

191235
hide();

0 commit comments

Comments
 (0)