Skip to content

Commit

Permalink
Merge branch 'master' into qa-one
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Schroer committed Sep 13, 2023
2 parents d0e2a66 + 5dcf812 commit 8560d0b
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 152 deletions.
16 changes: 13 additions & 3 deletions app/components/edit/EditNote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,20 @@ class EditNote extends Component<Props, State> {
handleChange,
note: { key },
} = this.props;
note.note = e.target.value;
this.setState({ note });
const newNote = {
...note,
note: e.target.value,
};

handleChange(key, note);
this.setState(
{
note: newNote,
},
() => {
const { note: stateNote } = this.state;
handleChange(key, stateNote);
}
);
}

render() {
Expand Down
189 changes: 72 additions & 117 deletions app/components/edit/EditNotes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Component } from "react";
import React, { useState, useEffect } from "react";
import EditNote from "./EditNote";
import { Note } from "../../models";

Expand All @@ -12,139 +12,94 @@ export interface InternalNoteChanges {
isRemoved?: boolean;
}

export type NewNotes = Record<number, InternalNoteChanges>;

type Props = {
notes: Note[] | undefined;
handleNotesChange: (n: State) => void;
};

export type State = {
notes: Record<number, InternalNoteChanges>;
existingNotes: InternalNote[];
uuid: number;
handleNotesChange: (newNotes: NewNotes) => void;
};

class EditNotes extends Component<Props, State> {
constructor(props: Props) {
super(props);

this.state = {
notes: {},
existingNotes: props.notes
? props.notes.map((note) => {
// HACK: This is bad because we are mutating the props to this
// component, which should never happen in a component. We should
// create a copy of the original Note before doing this, but before
// changing this code, we need to make sure that nothing else is relying on
// that mutation happening to the original Note props.
const newNote = note as InternalNote;
newNote.key = note.id;
return newNote;
})
: [],
uuid: -1,
const EditNotes = ({ notes = [], handleNotesChange }: Props) => {
const internalNotes = notes.map((note) => {
const newNote: InternalNote = {
...note,
key: note.id,
};

this.renderNotes = this.renderNotes.bind(this);
this.handleNoteChange = this.handleNoteChange.bind(this);
this.addNote = this.addNote.bind(this);
this.removeNote = this.removeNote.bind(this);
}

handleNoteChange(key: number, note: InternalNoteChanges): void {
const { notes } = this.state;
const { handleNotesChange } = this.props;
notes[key] = note;
this.setState(
{
notes,
},
() => {
// HACK: This is really strange, to pass in the entirety of the State of
// this component to a change handler. We should really be more
// selectively deciding what state should be synchronized to the parent
// component.
handleNotesChange(this.state);
}
);
}

addNote() {
const { existingNotes, uuid } = this.state;
const newUUID = uuid - 1;
existingNotes.push({
key: newUUID,
return newNote;
});

const [existingNotes, setExistingNotes] = useState(internalNotes);
const [uuid, setUuid] = useState(-1);
const [newNotes, setNewNotes] = useState<NewNotes>({});

useEffect(() => {
handleNotesChange(newNotes);
}, [newNotes, handleNotesChange]);

const handleNoteChange = (key: number, note: InternalNoteChanges): void => {
setNewNotes({
...newNotes,
[key]: note,
});
this.setState({ existingNotes, uuid: newUUID });
}

removeNote(index: number) {
const { handleNotesChange } = this.props;
const { existingNotes, notes } = this.state;
const currentNote = existingNotes[index];
currentNote.isRemoved = true;
const { key } = currentNote;
// HACK: This is really bad, and we shouldn't be directly mutating the state
// like this. Instead we should create a copy of the state variables we want
// to mutate and use `setState()` to update them.
// If we haven't created the note in our DB yet
// just remove it from the object locally
};

const addNote = () => {
setUuid(uuid - 1);
setExistingNotes([...existingNotes, { key: uuid }]);
};

const removeNote = (index: number) => {
const targetNote = existingNotes[index];
const { key } = targetNote;
const updatedExistingNotes = [...existingNotes];
const updatedNewNotes = { ...newNotes };

if (key < 0) {
delete notes[key];
delete updatedNewNotes[key];
} else {
notes[key] = { isRemoved: true };
updatedNewNotes[key] = { isRemoved: true };
}

this.setState(
{
notes,
existingNotes,
},
() => {
handleNotesChange(this.state);
}
);
}

renderNotes() {
const { existingNotes } = this.state;
return existingNotes.map((note, i) => (
updatedExistingNotes.splice(index, 1);
setExistingNotes(updatedExistingNotes);
setNewNotes(updatedNewNotes);
};

const renderNotes = () =>
existingNotes.map((note, i) => (
<EditNote
key={note.key}
index={i}
note={note}
handleChange={this.handleNoteChange}
removeNote={this.removeNote}
handleChange={handleNoteChange}
removeNote={removeNote}
/>
));
}

render() {
return (
<li className="edit--section--list--item edit--notes">
<label htmlFor="add-note">Notes</label>
<p>
<a
href="https://github.github.com/gfm/"
target="_blank"
rel="noopener noreferrer"
>
Markdown
</a>{" "}
is also supported for notes.
</p>
<ul className="edit--section--list--item--sublist">
{this.renderNotes()}
</ul>
<button
type="button"
className="edit--section--list--item--button"
onClick={this.addNote}

return (
<li className="edit--section--list--item edit--notes">
<label htmlFor="add-note">Notes</label>
<p>
<a
href="https://github.github.com/gfm/"
target="_blank"
rel="noopener noreferrer"
>
<i className="material-icons">add_box</i> Add Note
</button>
</li>
);
}
}
Markdown
</a>{" "}
is also supported for notes.
</p>
<ul className="edit--section--list--item--sublist">{renderNotes()}</ul>
<button
type="button"
className="edit--section--list--item--button"
onClick={addNote}
>
<i className="material-icons">add_box</i> Add Note
</button>
</li>
);
};

export default EditNotes;
13 changes: 12 additions & 1 deletion app/components/edit/ProvidedService.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ const TEXT_AREAS = [
"Describe what you'll receive from this service in a few sentences.",
field: "long_description",
},
{
label:
"Service Short Description (NOTE: THIS SHOULD ONLY BE MODIFIED FOR CERTAIN, SPECIAL CIRCUMSTANCES)",
placeholder:
"Describe what you'll receive from this service in a few sentences.",
field: "short_description",
},
{
label: "Application Process",
placeholder: "How do you apply for this service?",
Expand Down Expand Up @@ -266,7 +273,11 @@ const ProvidedService = ({
value: InternalTopLevelService[K]
) => {
const { id } = service;
editServiceById(id, { id, [field]: value });
const valueChanged = service[field] !== value;

if (valueChanged) {
editServiceById(id, { id, [field]: value });
}
};

const setShouldInheritScheduleFromParent = (shouldInherit: boolean) => {
Expand Down
2 changes: 1 addition & 1 deletion app/components/search/SearchResults/SearchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ const SearchResult = ({
};

const phoneNumber = hit?.phones?.[0]?.number;
const formatPhoneNumber = (number: string | number) => {
const formatPhoneNumber = (number: string) => {
// Takes 9 or 10 digit raw phone number input and outputs xxx-xxx-xxxx
// If the input doesn't match regex, function returns number's original value
if (!number) {
Expand Down
1 change: 1 addition & 0 deletions app/models/Service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface Service {
required_documents: any;
resource: Organization;
schedule: Schedule;
short_description: string;
source_attribution: string;
status: "pending" | "approved" | "rejected" | "inactive";
updated_at: string;
Expand Down
Loading

0 comments on commit 8560d0b

Please sign in to comment.