tsk-4: Fix contacts not being saved #14

Merged
phoenix merged 2 commits from tsk-4 into main 2026-07-04 10:53:33 -04:00
8 changed files with 62 additions and 42 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "textsender", "name": "textsender",
"version": "0.0.7", "version": "0.0.8",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "textsender", "name": "textsender",
"version": "0.0.7", "version": "0.0.8",
"dependencies": { "dependencies": {
"react": "^19.2.7", "react": "^19.2.7",
"react-dom": "^19.2.7", "react-dom": "^19.2.7",
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "textsender", "name": "textsender",
"private": true, "private": true,
"version": "0.0.7", "version": "0.0.8",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
+6 -5
View File
@@ -1,17 +1,18 @@
import { API_BASE_URL } from '../constants/api'; import { API_BASE_URL } from '../constants/api';
export class CreateContactRequest { export class CreateContactRequest {
first_name = ''; firstname = '';
last_name = ''; lastname = '';
nickname = '';
phone_number = ''; phone_number = '';
user_id = ''; user_id = '';
} }
export class UpdateContactNamesRequest { export class UpdateContactNamesRequest {
first_name = ''; firstname = '';
last_name = ''; lastname = '';
nickname = ''; nickname = '';
contact_id = ''; id = '';
user_id = ''; user_id = '';
} }
+21 -2
View File
@@ -11,6 +11,7 @@ const AddContact = ({ isOpen, onClose, onSuccess }) => {
phoneNumber: '', phoneNumber: '',
firstName: '', firstName: '',
lastName: '', lastName: '',
nickName: '',
}); });
const [errors, setErrors] = useState({}); const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
@@ -66,8 +67,9 @@ const AddContact = ({ isOpen, onClose, onSuccess }) => {
const userId = tokenService.getUserId(); const userId = tokenService.getUserId();
let contact = new CreateContactRequest(); let contact = new CreateContactRequest();
contact.phone_number = formData.phoneNumber; contact.phone_number = formData.phoneNumber;
contact.first_name = formData.firstName; contact.firstname = formData.firstName;
contact.last_name = formData.lastName; contact.lastname = formData.lastName;
contact.nickname = formData.nickName;
contact.user_id = userId; contact.user_id = userId;
const result = await contactApi.createContact( const result = await contactApi.createContact(
contact, contact,
@@ -178,6 +180,23 @@ const AddContact = ({ isOpen, onClose, onSuccess }) => {
<span className="form-hint">Optional field</span> <span className="form-hint">Optional field</span>
</div> </div>
<div className="form-group">
<label htmlFor="nickName" className="form-label">
Nick Name
</label>
<input
id="nickName"
name="nickName"
type="text"
className="form-input"
value={formData.nickName}
onChange={handleChange}
placeholder="Enter nick name (optional)"
disabled={isSubmitting}
/>
<span className="form-hint">Optional field</span>
</div>
<div className="form-actions"> <div className="form-actions">
<button <button
type="button" type="button"
@@ -33,11 +33,11 @@ function ConfirmationStep({ selectedContact, contactDetails, isSubmitting }) {
<span className={styles.reviewLabel}>First Name</span> <span className={styles.reviewLabel}>First Name</span>
<div className={styles.reviewComparison}> <div className={styles.reviewComparison}>
<span className={styles.oldValue}> <span className={styles.oldValue}>
{selectedContact.first_name || 'Not set'} {selectedContact.firstname || 'Not set'}
</span> </span>
<span className={styles.arrow}></span> <span className={styles.arrow}></span>
<span className={styles.newValue}> <span className={styles.newValue}>
{contactDetails.first_name || 'Not set'} {contactDetails.firstname || 'Not set'}
</span> </span>
</div> </div>
</div> </div>
@@ -46,11 +46,11 @@ function ConfirmationStep({ selectedContact, contactDetails, isSubmitting }) {
<span className={styles.reviewLabel}>Last Name</span> <span className={styles.reviewLabel}>Last Name</span>
<div className={styles.reviewComparison}> <div className={styles.reviewComparison}>
<span className={styles.oldValue}> <span className={styles.oldValue}>
{selectedContact.last_name || 'Not set'} {selectedContact.lastname || 'Not set'}
</span> </span>
<span className={styles.arrow}></span> <span className={styles.arrow}></span>
<span className={styles.newValue}> <span className={styles.newValue}>
{contactDetails.last_name || 'Not set'} {contactDetails.lastname || 'Not set'}
</span> </span>
</div> </div>
</div> </div>
+12 -12
View File
@@ -3,8 +3,8 @@ import styles from './ModifyForm.module.css';
function ModifyForm({ contactDetails, setContactDetails }) { function ModifyForm({ contactDetails, setContactDetails }) {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
first_name: '', firstname: '',
last_name: '', lastname: '',
nickname: '', nickname: '',
}); });
@@ -12,8 +12,8 @@ function ModifyForm({ contactDetails, setContactDetails }) {
useEffect(() => { useEffect(() => {
if (contactDetails) { if (contactDetails) {
setFormData({ setFormData({
first_name: contactDetails.first_name || '', firstname: contactDetails.firstname || '',
last_name: contactDetails.last_name || '', lastname: contactDetails.lastname || '',
nickname: contactDetails.nickname || '', nickname: contactDetails.nickname || '',
}); });
} }
@@ -37,16 +37,16 @@ function ModifyForm({ contactDetails, setContactDetails }) {
<h3 className={styles.sectionTitle}>Edit Contact Information</h3> <h3 className={styles.sectionTitle}>Edit Contact Information</h3>
<div className={styles.formGroup}> <div className={styles.formGroup}>
<label htmlFor="first_name" className={styles.formLabel}> <label htmlFor="firstname" className={styles.formLabel}>
First Name First Name
<span className={styles.requiredIndicator}>*</span> <span className={styles.requiredIndicator}>*</span>
</label> </label>
<div className={styles.inputContainer}> <div className={styles.inputContainer}>
<input <input
type="text" type="text"
id="first_name" id="firstname"
name="first_name" name="firstname"
value={formData.first_name} value={formData.firstname}
onChange={handleChange} onChange={handleChange}
className={styles.formInput} className={styles.formInput}
placeholder="Enter contact's first name" placeholder="Enter contact's first name"
@@ -61,16 +61,16 @@ function ModifyForm({ contactDetails, setContactDetails }) {
</div> </div>
<div className={styles.formGroup}> <div className={styles.formGroup}>
<label htmlFor="last_name" className={styles.formLabel}> <label htmlFor="lastname" className={styles.formLabel}>
Last Name Last Name
<span className={styles.requiredIndicator}>*</span> <span className={styles.requiredIndicator}>*</span>
</label> </label>
<div className={styles.inputContainer}> <div className={styles.inputContainer}>
<input <input
type="text" type="text"
id="last_name" id="lastname"
name="last_name" name="lastname"
value={formData.last_name} value={formData.lastname}
onChange={handleChange} onChange={handleChange}
className={styles.formInput} className={styles.formInput}
placeholder="Enter contact's last name" placeholder="Enter contact's last name"
@@ -49,15 +49,15 @@ function ViewContact({ selectedContact, onSelectedContact }) {
const filteredContacts = contacts.filter( const filteredContacts = contacts.filter(
(contact) => (contact) =>
contact.phone_number.toLowerCase().includes(searchTerm.toLowerCase()) || contact.phone_number.toLowerCase().includes(searchTerm.toLowerCase()) ||
contact.first_name?.toLowerCase().includes(searchTerm.toLowerCase()) || contact.firstname?.toLowerCase().includes(searchTerm.toLowerCase()) ||
contact.last_name?.toLowerCase().includes(searchTerm.toLowerCase()) || contact.lastname?.toLowerCase().includes(searchTerm.toLowerCase()) ||
contact.nickname?.toLowerCase().includes(searchTerm.toLowerCase()) contact.nickname?.toLowerCase().includes(searchTerm.toLowerCase())
); );
const formatContactDisplay = (contact) => { const formatContactDisplay = (contact) => {
const phone = contact.phone_number || 'No phone'; const phone = contact.phone_number || 'No phone';
const name = const name =
[contact.first_name, contact.last_name].filter(Boolean).join(' ') || [contact.firstname, contact.lastname].filter(Boolean).join(' ') ||
'Unnamed'; 'Unnamed';
const nickname = contact.nickname ? `"${contact.nickname}"` : ''; const nickname = contact.nickname ? `"${contact.nickname}"` : '';
@@ -117,7 +117,7 @@ function ViewContact({ selectedContact, onSelectedContact }) {
onClick={() => onSelectedContact(contact)} onClick={() => onSelectedContact(contact)}
> >
<div className={styles.contactAvatar}> <div className={styles.contactAvatar}>
{contact.first_name?.[0]?.toUpperCase() || '?'} {contact.firstname?.[0]?.toUpperCase() || '?'}
</div> </div>
<div className={styles.contactInfo}> <div className={styles.contactInfo}>
<div className={styles.contactMainInfo}> <div className={styles.contactMainInfo}>
@@ -131,7 +131,7 @@ function ViewContact({ selectedContact, onSelectedContact }) {
)} )}
</div> </div>
<div className={styles.contactName}> <div className={styles.contactName}>
{[contact.first_name, contact.last_name] {[contact.firstname, contact.lastname]
.filter(Boolean) .filter(Boolean)
.join(' ') || 'Unnamed Contact'} .join(' ') || 'Unnamed Contact'}
</div> </div>
@@ -21,13 +21,13 @@ const useViewContactWizard = () => {
case 'modify': case 'modify':
if (!state.contactDetails) return false; if (!state.contactDetails) return false;
if ( if (
!state.contactDetails.first_name || !state.contactDetails.firstname ||
state.contactDetails.first_name.trim() === '' state.contactDetails.firstname.trim() === ''
) { ) {
return false; return false;
} else if ( } else if (
!state.contactDetails.last_name || !state.contactDetails.lastname ||
state.contactDetails.last_name.trim() === '' state.contactDetails.lastname.trim() === ''
) { ) {
return false; return false;
} else { } else {
@@ -61,8 +61,8 @@ const useViewContactWizard = () => {
? null ? null
: { : {
id: contactId, id: contactId,
first_name: contact.first_name, firstname: contact.firstname,
last_name: contact.last_name, lastname: contact.lastname,
phone_number: contact.phone_number, phone_number: contact.phone_number,
user_id: contact.user_id, user_id: contact.user_id,
nickname: contact.nickname || '', nickname: contact.nickname || '',
@@ -90,8 +90,8 @@ const useViewContactWizard = () => {
step: nextStepValue, step: nextStepValue,
submissionError: null, submissionError: null,
contactDetails: { contactDetails: {
first_name: prev.selectedContact.first_name || '', firstname: prev.selectedContact.firstname || '',
last_name: prev.selectedContact.last_name || '', lastname: prev.selectedContact.lastname || '',
nickname: prev.selectedContact.nickname || '', nickname: prev.selectedContact.nickname || '',
phone_number: prev.selectedContact.phone_number || '', phone_number: prev.selectedContact.phone_number || '',
id: prev.selectedContact.id, id: prev.selectedContact.id,
@@ -139,10 +139,10 @@ const useViewContactWizard = () => {
console.log('Contact details to update: ', state.contactDetails); console.log('Contact details to update: ', state.contactDetails);
let reqBody = new UpdateContactNamesRequest(); let reqBody = new UpdateContactNamesRequest();
reqBody.first_name = state.contactDetails.first_name; reqBody.firstname = state.contactDetails.firstname;
reqBody.last_name = state.contactDetails.last_name; reqBody.lastname = state.contactDetails.lastname;
reqBody.nickname = state.contactDetails.nickname || ''; // Send empty string if no nickname reqBody.nickname = state.contactDetails.nickname || ''; // Send empty string if no nickname
reqBody.contact_id = state.selectedContact.id; reqBody.id = state.selectedContact.id;
reqBody.user_id = userId; reqBody.user_id = userId;
const response = await contactApi.updateContactNames( const response = await contactApi.updateContactNames(