diff --git a/app/appdb.cls b/app/appdb.cls index 20d69a3..3a5bf69 100644 --- a/app/appdb.cls +++ b/app/appdb.cls @@ -88,7 +88,7 @@ self~addPhoneNumber(contactId, contactDict["PHONE_TYPE"], contactDict["PHONE_NUMBER"]) self~addEmailAddress(contactId, contactDict["EMAIL_TYPE"], contactDict["EMAIL_ADDRESS"]) /* contactId, addressType, street, city, state, postalCode, country */ - self~addRealAddress(contactId, "NA", contactDict~street, contactDict~city, contactDict~state, contactDict~postCode, "NA") + self~addRealAddress(contactId, "NA", contactDict~street, contactDict~city, contactDict~state, contactDict~postCode, contactDict~country) return contactId ::METHOD getContact @@ -213,13 +213,16 @@ ***********************/ ::METHOD updateContact expose db - use arg contactId, firstName, lastName - sql = "UPDATE contacts SET first_name = '"firstName"', last_name = '"lastName"' WHERE id = "contactId - rc = db~exec(sql) - if rc \= 0 then do - say "Error updating contact:" db~errMsg() - return -1 - end + use arg contactId, contactDict + rc = 0 + sql1 = "UPDATE contacts SET first_name = '"contactDict~first_Name"', last_name = '"contactDict~last_Name"' WHERE id = "contactId + rc = db~exec(sql1) + sql2 = "UPDATE phone_numbers SET number = '"contactDict~phone_number"', type = '"contactDict~phone_type"' WHERE contact_id = "contactId + rc = db~exec(sql2) + sql3 = "UPDATE email_addresses SET email = '"contactDict~email_address"', type = '"contactDict~email_type"' WHERE contact_id = "contactId + rc = db~exec(sql3) + sql4 = "UPDATE addresses SET street = '"contactDict~street"', city = '"contactDict~city"', state = '"contactDict~state"', postal_code = '"contactDict~postcode"', country = '"contactDict~country"' WHERE contact_id = "contactId + rc = db~exec(sql4) return rc /************************** diff --git a/app/appui.cls b/app/appui.cls index f633369..2118ae2 100644 --- a/app/appui.cls +++ b/app/appui.cls @@ -13,7 +13,7 @@ ::method initialize expose win mainMenu db - win = self~DrawMainPanel(0, .true) /* default colour, draw border box */ + win = self~DrawMainPanel(0, .false) /* default colour, no main border */ self~setupMainMenu(win) return @@ -79,6 +79,10 @@ when clrset = 9 then panel~init_pair(10, panel~COLOR_BLACK, panel~COLOR_BLACK) /* red on black */ when clrset = 10 then panel~init_pair(11, panel~COLOR_RED, panel~COLOR_BLACK) + /* yellow on black */ + when clrset = 11 then panel~init_pair(12, panel~COLOR_YELLOW, panel~COLOR_BLACK) + /* green on black */ + when clrset = 12 then panel~init_pair(13, panel~COLOR_GREEN, panel~COLOR_BLACK) /* Default to white text on black background */ OTHERWISE DO clrset=0 @@ -152,8 +156,9 @@ menuwin~refresh() RETURN - /********************** - * Add new contact * + /************************************* ADD CONTACT **************************************/ + /********************** + * Add new contact * **********************/ ::method addContactPanel expose win db menuwin formwin @@ -165,7 +170,7 @@ form_width = 60 start_y = (max_y - form_height) % 2 start_x = (max_x - form_width) % 2 - formwin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 0, "Add New Contact", .true) + formwin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 12, "Add New Contact", .true) /* Create form fields */ formwin~mvaddstr(3, 2, "First Name: ") @@ -174,61 +179,67 @@ formwin~mvaddstr(6, 2, "Email: "); formwin~mvaddstr(6, 42, "Type: "); formwin~mvaddstr(7, 2, "Street: ") formwin~mvaddstr(8, 2, "City: "); formwin~mvaddstr(8, 28, "State: "); formwin~mvaddstr(8, 40, "PostCode: ") + formwin~mvaddstr(9, 2, "Country: ") formwin~mvaddstr(form_height-2, 2, "[Enter] to save, [Esc] to cancel") formwin~refresh() /* Input fields */ - firstName = self~getInputField(formwin, 3, 14, 30) + firstName = self~getInputField(formwin, 3, 14, 30, '') if firstName = .nil then do self~dropWindow(formwin) RETURN END - lastName = self~getInputField(formwin, 4, 14, 30) + lastName = self~getInputField(formwin, 4, 14, 30, '') if lastName = .nil then do self~dropWindow(formwin) RETURN END - phone = self~getInputField(formwin, 5, 10, 15) + phone = self~getInputField(formwin, 5, 10, 15, '') if phone = .nil then do self~dropWindow(formwin) RETURN END - phone_type = self~getInputField(formwin, 5, 48, 15) + phone_type = self~getInputField(formwin, 5, 48, 15, '') if phone_type = .nil then do self~dropWindow(formwin) RETURN END - email = self~getInputField(formwin, 6, 10, 30) + email = self~getInputField(formwin, 6, 10, 30, '') if email = .nil then do self~dropWindow(formwin) RETURN END - email_type = self~getInputField(formwin, 6, 48, 15) + email_type = self~getInputField(formwin, 6, 48, 15, '') if email_type = .nil then do self~dropWindow(formwin) RETURN END - street = self~getInputField(formwin, 7, 10, 25) + street = self~getInputField(formwin, 7, 10, 25, '') if street = .nil then do self~dropWindow(formwin) RETURN END - city = self~getInputField(formwin, 8, 10, 15) + city = self~getInputField(formwin, 8, 10, 15, '') if city = .nil then do self~dropWindow(formwin) RETURN END - state = self~getInputField(formwin, 8, 35, 2) + state = self~getInputField(formwin, 8, 35, 2, '') if state = .nil then do self~dropWindow(formwin) RETURN END - postCode = self~getInputField(formwin, 8, 50, 10) + postCode = self~getInputField(formwin, 8, 50, 10, '') if postCode = .nil then do self~dropWindow(formwin) RETURN END + country = self~getInputField(formwin, 9, 10, 15, '') + if country = .nil then do + self~dropWindow(formwin) + RETURN + END if firstname = "" | lastname = "" then do formwin~mvaddstr(8, 2, "First and Last names are required.") @@ -248,6 +259,7 @@ contactDict["CITY"] = city contactDict["STATE"] = state contactDict["POSTCODE"] = postCode + contactDict["COUNTRY"] = country result = db~addContact(contactDict) /* Display result message */ @@ -265,6 +277,202 @@ self~dropWindow(formwin) RETURN + /************************************* EDIT CONTACT **************************************/ + + /***************************** + * Edit Contact Select Panel * + *****************************/ + ::METHOD editContactSelectPanel + expose win db menuwin ewin + + /* Create a form panel */ + max_y = win~lines + max_x = win~cols + form_height = 12 + form_width = 35 + start_y = (max_y - form_height) % 2 + start_x = (max_x - form_width) % 2 + ewin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 11, "Select A Contact To Edit", .true) + + ewin~mvaddstr(4, 2, "Contact ID: ") + ewin~mvaddstr(form_height-1, 2, "[Enter] to edit, [Esc] to cancel") + ewin~refresh() + + contactId = self~getInputField(ewin, 4, 14, 10, '') + if contactId = .nil then do + self~dropWindow(ewin) + RETURN + END + + result = db~getContact(contactId) + + if result = .nil then do /* should be a result id number */ + ewin~mvaddstr(8, 2, "Contact not found.") + ewin~refresh() + call SysWait 0.5 + self~dropWindow(ewin) + RETURN + end + + /* launch a view panel with full contact details */ + self~dropWindow(ewin) + self~editContactDetailsPanel(contactId) + RETURN + + /************************* + * Edit Existing Contact * + *************************/ + ::METHOD editContactDetailsPanel + expose win db menuwin editwin + use arg contactId + + /* Create a form panel */ + max_y = win~lines + max_x = win~cols + form_height = 15 + form_width = 60 + start_y = (max_y - form_height) % 2 + start_x = (max_x - form_width) % 2 + editwin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 11, "Edit Contact Details", .true) + + /* Create form fields */ + editwin~mvaddstr(3, 2, "First Name: ") + editwin~mvaddstr(4, 2, "Last Name: ") + editwin~mvaddstr(5, 2, "Phone: "); editwin~mvaddstr(5, 42, "Type: "); + editwin~mvaddstr(6, 2, "Email: "); editwin~mvaddstr(6, 42, "Type: "); + editwin~mvaddstr(7, 2, "Street: ") + editwin~mvaddstr(8, 2, "City: "); editwin~mvaddstr(8, 28, "State: "); editwin~mvaddstr(8, 40, "PostCode: ") + editwin~mvaddstr(9, 2, "Country: ") + editwin~mvaddstr(form_height-1, 2, "[Enter] to save, [Esc] to cancel") + editwin~refresh() + + /* Get existing details */ + contactDetails = db~getContactDetails(contactId) + + editwin~mvaddstr(3, 14, contactDetails~first_name); + editwin~mvaddstr(4, 14, contactDetails~last_name); + editwin~mvaddstr(5, 10, contactDetails~phone_number); + editwin~mvaddstr(5, 48, contactDetails~phone_type); + editwin~mvaddstr(6, 10, contactDetails~email_address); + editwin~mvaddstr(6, 48, contactDetails~email_type); + editwin~mvaddstr(7, 10, contactDetails~street); + editwin~mvaddstr(8, 10, contactDetails~city); + editwin~mvaddstr(8, 35, contactDetails~state); + editwin~mvaddstr(8, 50, contactDetails~postal_code); + editwin~mvaddstr(9, 10, contactDetails~country); + + /* Prepopulate the input fields */ + firstNameInit = contactDetails~first_name + lastNameInit = contactDetails~last_name + phoneInit = contactDetails~phone_number + phone_typeInit = contactDetails~phone_type + emailInit = contactDetails~email_address + email_typeInit = contactDetails~email_type + streetInit = contactDetails~street + cityInit = contactDetails~city + stateInit = contactDetails~state + postCodeInit = contactDetails~postal_code + countryInit = contactDetails~country + + /* Input fields */ + firstName = self~getInputField(editwin, 3, 14, 30, firstNameInit) + if firstName = .nil then do + self~dropWindow(editwin) + RETURN + END + + lastName = self~getInputField(editwin, 4, 14, 30, lastNameInit) + if lastName = .nil then do + self~dropWindow(editwin) + RETURN + END + + phone = self~getInputField(editwin, 5, 10, 15, phoneInit) + if phone = .nil then do + self~dropWindow(editwin) + RETURN + END + + phone_type = self~getInputField(editwin, 5, 48, 15, phone_typeInit) + if phone_type = .nil then do + self~dropWindow(editwin) + RETURN + END + + email = self~getInputField(editwin, 6, 10, 30, emailInit) + if email = .nil then do + self~dropWindow(editwin) + RETURN + END + + email_type = self~getInputField(editwin, 6, 48, 15, email_typeInit) + if email_type = .nil then do + self~dropWindow(editwin) + RETURN + END + + street = self~getInputField(editwin, 7, 10, 30, streetInit) + if street = .nil then do + self~dropWindow(editwin) + RETURN + END + + city = self~getInputField(editwin, 8, 10, 15, cityInit) + if city = .nil then do + self~dropWindow(editwin) + RETURN + END + + state = self~getInputField(editwin, 8, 35, 2, stateInit) + if state = .nil then do + self~dropWindow(editwin) + RETURN + END + + postCode = self~getInputField(editwin, 8, 50, 10, postCodeInit) + if postCode = .nil then do + self~dropWindow(editwin) + RETURN + END + + country = self~getInputField(editwin, 9, 10, 15, countryInit) + if country = .nil then do + self~dropWindow(editwin) + RETURN + END + + /* Add to database */ + contactDict = .Directory~new() + contactDict["FIRST_NAME"] = firstName + contactDict["LAST_NAME"] = lastName + contactDict["PHONE_NUMBER"] = phone + contactDict["PHONE_TYPE"] = phone_type + contactDict["EMAIL_ADDRESS"] = email + contactDict["EMAIL_TYPE"] = email_type + contactDict["STREET"] = street + contactDict["CITY"] = city + contactDict["STATE"] = state + contactDict["POSTCODE"] = postCode + contactDict["COUNTRY"] = country + + result = db~updateContact(contactId, contactDict) + + /* Display result message */ + if result = 0 then do /* should be a result id number */ + editwin~mvaddstr(11, 2, "Contact ID ["result"] edited successfully!") + editwin~refresh() + call SysWait 1.5 + end + else do + editwin~mvaddstr(11, 2, "Failed to edit contact.") + editwin~refresh() + call SysWait 1.5 + end + self~dropWindow(editwin) + RETURN + + /************************************* DELETE CONTACT **************************************/ + /**************************** * Delete Contact Panel * ****************************/ @@ -284,7 +492,7 @@ delwin~mvaddstr(form_height-1, 2, "[Enter] to del, [Esc] to cancel") delwin~refresh() - contactId = self~getInputField(delwin, 4, 14, 10) + contactId = self~getInputField(delwin, 4, 14, 10, '') if contactId = .nil then do self~dropWindow(delwin) RETURN @@ -305,6 +513,8 @@ self~dropWindow(delwin) RETURN + /************************************* VIEW CONTACT **************************************/ + /******************************** * View Contact Selection Panel * ********************************/ @@ -324,7 +534,7 @@ viewselectwin~mvaddstr(form_height-1, 2, "[Enter] to sel., [Esc] to cancel") viewselectwin~refresh() - contactId = self~getInputField(viewselectwin, 4, 14, 10) + contactId = self~getInputField(viewselectwin, 4, 14, 10, '') if contactId = .nil then do self~dropWindow(viewselectwin) RETURN @@ -383,6 +593,8 @@ RETURN + /************************************* VIEW ALL CONTACTS **********************************/ + /**************************** * List all contacts * ****************************/ @@ -393,7 +605,7 @@ max_y = win~lines max_x = win~cols list_height = max_y - 10 - list_width = max_x - 30 + list_width = max_x - 18 start_y = (max_y - list_height) % 2 start_x = (max_x - list_width) % 2 @@ -404,11 +616,11 @@ /* Display column headers */ listwin~attron(listwin~A_BOLD) listwin~mvaddstr(4, 2, "ID") - listwin~mvaddstr(4, 5, "First Name") - listwin~mvaddstr(4, 17, "Last Name") - listwin~mvaddstr(4, 29, "Phone") - listwin~mvaddstr(4, 45, "Email") - listwin~mvaddstr(5, 2, "-- ---------- --------- --------------- -------------------------") + listwin~mvaddstr(4, 7, "First Name") + listwin~mvaddstr(4, 21, "Last Name") + listwin~mvaddstr(4, 36, "Phone") + listwin~mvaddstr(4, 52, "Email") + listwin~mvaddstr(5, 2, "---- ---------- ------------ --------------- -------------------------") listwin~attroff(listwin~A_BOLD) contacts = db~getAllContacts() @@ -418,10 +630,10 @@ do i = 1 to contacts~items contact = contacts[i] listwin~mvaddstr(i+5, 2, contact['ID']) - listwin~mvaddstr(i+5, 5, contact['FIRST_NAME']) - listwin~mvaddstr(i+5, 17, contact['LAST_NAME']) - listwin~mvaddstr(i+5, 29, contact['PHONE_NUMBER']) - listwin~mvaddstr(i+5, 45, contact['EMAIL_ADDRESS']) + listwin~mvaddstr(i+5, 7, contact['FIRST_NAME']) + listwin~mvaddstr(i+5, 21, contact['LAST_NAME']) + listwin~mvaddstr(i+5, 36, contact['PHONE_NUMBER']) + listwin~mvaddstr(i+5, 52, contact['EMAIL_ADDRESS']) /* Break if we run out of screen space */ if i > list_height-7 then LEAVE end @@ -435,6 +647,8 @@ RETURN Return + /************************************* SEARCH ALL CONTACTS ***********************************/ + /**************************** * Search for contact * ****************************/ @@ -454,7 +668,7 @@ searchwin~refresh() /* Get search term */ - term = self~getInputField(searchwin, 3, 15, 30) + term = self~getInputField(searchwin, 3, 15, 30, '') /* If canceled, return to main menu */ if term = .nil then do @@ -482,7 +696,7 @@ max_y = win~lines max_x = win~cols list_height = max_y - 15 - list_width = max_x - 30 + list_width = max_x - 18 start_y = (max_y - list_height) % 2 start_x = (max_x - list_width) % 2 @@ -493,11 +707,11 @@ /* Display column headers */ searchoutwin~attron(searchoutwin~A_BOLD) searchoutwin~mvaddstr(4, 2, "ID") - searchoutwin~mvaddstr(4, 5, "First Name") - searchoutwin~mvaddstr(4, 17, "Last Name") - searchoutwin~mvaddstr(4, 29, "Phone") - searchoutwin~mvaddstr(4, 45, "Email") - searchoutwin~mvaddstr(5, 2, "-- ---------- --------- --------------- -------------------------") + searchoutwin~mvaddstr(4, 7, "First Name") + searchoutwin~mvaddstr(4, 21, "Last Name") + searchoutwin~mvaddstr(4, 36, "Phone") + searchoutwin~mvaddstr(4, 52, "Email") + searchoutwin~mvaddstr(5, 2, "---- ---------- ------------ --------------- -------------------------") searchoutwin~attroff(searchoutwin~A_BOLD) contacts = db~searchContacts(term) @@ -507,10 +721,10 @@ do i = 1 to contacts~items contact = contacts[i] searchoutwin~mvaddstr(i+5, 2, contact['ID']) - searchoutwin~mvaddstr(i+5, 5, contact['FIRST_NAME']) - searchoutwin~mvaddstr(i+5, 17, contact['LAST_NAME']) - searchoutwin~mvaddstr(i+5, 29, contact['PHONE_NUMBER']) - searchoutwin~mvaddstr(i+5, 45, contact['EMAIL_ADDRESS']) + searchoutwin~mvaddstr(i+5, 7, contact['FIRST_NAME']) + searchoutwin~mvaddstr(i+5, 21, contact['LAST_NAME']) + searchoutwin~mvaddstr(i+5, 36, contact['PHONE_NUMBER']) + searchoutwin~mvaddstr(i+5, 52, contact['EMAIL_ADDRESS']) /* Break if we run out of screen space */ if i > list_height-7 then LEAVE end @@ -524,29 +738,33 @@ RETURN + /************************************* UTILITIY METHODS **************************************/ + /************************ * Get Input From Field * ************************/ ::method getInputField - use arg win, y, x, maxlen + use arg win, y, x, maxlen, bufferContent - win~move(y, x) win~curs_set(1) /* Show cursor */ win~keypad(1) /* Enable function keys and arrow keys */ win~echo() /* Show typed characters */ win~raw - buffer = "" + if LENGTH(bufferContent) > 0 then DO + buffer = bufferContent + win~move(y, x + buffer~length) + END + Else DO + buffer = "" + win~move(y, x) + END + blank_line = copies(" ", maxlen) /* String of spaces for clearing the line */ do forever key = win~getch() - - decimalKey = C2D(key) - /* Debug: Display key decimal value */ - /* win~mvaddstr(12, 2, "Key pressed (decimal): " || decimalKey || " ") */ - - + decimalKey = C2D(key) select when key = D2C(27) then do /* ESC key */ win~curs_set(0) /* Hide cursor */ @@ -646,8 +864,7 @@ self~deleteContactPanel() END when key_char = 'e' then do - menuwin~mvaddstr(menuwin~lines-15, 3, "TODO: Create Edit Panel"); - menuwin~refresh + self~editContactSelectPanel() END when key_char = 's' then do self~searchContactPanel() diff --git a/db/contacts.sqlite b/db/contacts.sqlite index ba7c7b1..90a3bc8 100644 Binary files a/db/contacts.sqlite and b/db/contacts.sqlite differ