Skip to content

Instantly share code, notes, and snippets.

@npras
Created June 27, 2026 14:21
Show Gist options
  • Select an option

  • Save npras/f093f02fd396e818522646c351cd3c74 to your computer and use it in GitHub Desktop.

Select an option

Save npras/f093f02fd396e818522646c351cd3c74 to your computer and use it in GitHub Desktop.
fcc certification - relational db - salon appointment
#!/bin/bash
psql="psql --username=freecodecamp --dbname=salon -X -A -t -c"
# use a hash to store ids instead of regular arrays because of fast lookup ability
declare -A service_id_to_name
# use this reg array to keep track of service record order, based on service id
service_order=()
welcome() {
echo -e "\n~~~~~ MY SALON ~~~~~\n"
echo -e "Welcome to My Salon, how can I help you?\n"
}
gather_services() {
services_result="$($psql "select service_id, name from services order by service_id;")"
while IFS='|' read -r service_id service_name; do
service_id_to_name[$service_id]="$service_name"
service_order+=( $service_id )
done <<< "$services_result"
}
list_services_and_await_user_input() {
for service_id in "${service_order[@]}"; do
echo "${service_id}) ${service_id_to_name[$service_id]}"
done
read SERVICE_ID_SELECTED
# check if it's there in our 'cache'
selected_service="${service_id_to_name[$SERVICE_ID_SELECTED]}"
if [[ -z "$selected_service" ]]; then
echo -e "\nI could not find that service. What would you like today?"
list_services_and_await_user_input
else
gather_info_and_fix_appointment "$SERVICE_ID_SELECTED" "$selected_service"
fi
}
# ask phone.
# if phone in db, fix appointment and exit.
# if not, ask name and create customer record, then fix appointment and exit
gather_info_and_fix_appointment() {
service_id="$1"
service_name="$2"
echo -e "\nWhat's your phone number?"
read CUSTOMER_PHONE
customer_result=$($psql "select customer_id, name from customers where phone = '$CUSTOMER_PHONE';")
IFS='|' read -r customer_id customer_name <<< "$customer_result"
if [[ -z "$customer_result" ]]; then
# ask name, create customer record, get back customer_id
echo -e "\nI don't have a record for that phone number, what's your name?"
read CUSTOMER_NAME
customer_result=$($psql "with insert_cte as (insert into customers (name, phone) values ('$CUSTOMER_NAME', '$CUSTOMER_PHONE') returning customer_id, name) select customer_id, name from insert_cte;")
IFS='|' read -r customer_id customer_name <<< "$customer_result"
fi
echo -e "\nWhat time would you like your $service_name, ${customer_name}?"
read SERVICE_TIME
fix_appointment "$service_id" "$service_name" "$customer_id" "$customer_name" "$SERVICE_TIME"
}
fix_appointment() {
service_id="$1"
service_name="$2"
customer_id="$3"
customer_name="$4"
appointment_time="$5"
appointment_insert_result=$($psql "insert into appointments (service_id, customer_id, time) values ($service_id, $customer_id, '$appointment_time');")
if [[ "$appointment_insert_result" == "INSERT 0 1" ]]; then
echo -e "\nI have put you down for a ${service_name} at ${appointment_time}, ${customer_name}.\n"
fi
}
welcome
gather_services
list_services_and_await_user_input
--
-- PostgreSQL database dump
--
-- Dumped from database version 12.22 (Ubuntu 12.22-0ubuntu0.20.04.4)
-- Dumped by pg_dump version 12.22 (Ubuntu 12.22-0ubuntu0.20.04.4)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
DROP DATABASE salon;
--
-- Name: salon; Type: DATABASE; Schema: -; Owner: freecodecamp
--
CREATE DATABASE salon WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'C.UTF-8' LC_CTYPE = 'C.UTF-8';
ALTER DATABASE salon OWNER TO freecodecamp;
\connect salon
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
SET default_tablespace = '';
SET default_table_access_method = heap;
--
-- Name: appointments; Type: TABLE; Schema: public; Owner: freecodecamp
--
CREATE TABLE public.appointments (
appointment_id integer NOT NULL,
customer_id integer NOT NULL,
service_id integer NOT NULL,
"time" character varying(50) NOT NULL
);
ALTER TABLE public.appointments OWNER TO freecodecamp;
--
-- Name: appointments_appointment_id_seq; Type: SEQUENCE; Schema: public; Owner: freecodecamp
--
CREATE SEQUENCE public.appointments_appointment_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.appointments_appointment_id_seq OWNER TO freecodecamp;
--
-- Name: appointments_appointment_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: freecodecamp
--
ALTER SEQUENCE public.appointments_appointment_id_seq OWNED BY public.appointments.appointment_id;
--
-- Name: customers; Type: TABLE; Schema: public; Owner: freecodecamp
--
CREATE TABLE public.customers (
customer_id integer NOT NULL,
name character varying(50) NOT NULL,
phone character varying(10) NOT NULL
);
ALTER TABLE public.customers OWNER TO freecodecamp;
--
-- Name: customers_customer_id_seq; Type: SEQUENCE; Schema: public; Owner: freecodecamp
--
CREATE SEQUENCE public.customers_customer_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.customers_customer_id_seq OWNER TO freecodecamp;
--
-- Name: customers_customer_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: freecodecamp
--
ALTER SEQUENCE public.customers_customer_id_seq OWNED BY public.customers.customer_id;
--
-- Name: services; Type: TABLE; Schema: public; Owner: freecodecamp
--
CREATE TABLE public.services (
service_id integer NOT NULL,
name character varying(50) NOT NULL
);
ALTER TABLE public.services OWNER TO freecodecamp;
--
-- Name: services_service_id_seq; Type: SEQUENCE; Schema: public; Owner: freecodecamp
--
CREATE SEQUENCE public.services_service_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public.services_service_id_seq OWNER TO freecodecamp;
--
-- Name: services_service_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: freecodecamp
--
ALTER SEQUENCE public.services_service_id_seq OWNED BY public.services.service_id;
--
-- Name: appointments appointment_id; Type: DEFAULT; Schema: public; Owner: freecodecamp
--
ALTER TABLE ONLY public.appointments ALTER COLUMN appointment_id SET DEFAULT nextval('public.appointments_appointment_id_seq'::regclass);
--
-- Name: customers customer_id; Type: DEFAULT; Schema: public; Owner: freecodecamp
--
ALTER TABLE ONLY public.customers ALTER COLUMN customer_id SET DEFAULT nextval('public.customers_customer_id_seq'::regclass);
--
-- Name: services service_id; Type: DEFAULT; Schema: public; Owner: freecodecamp
--
ALTER TABLE ONLY public.services ALTER COLUMN service_id SET DEFAULT nextval('public.services_service_id_seq'::regclass);
--
-- Data for Name: appointments; Type: TABLE DATA; Schema: public; Owner: freecodecamp
--
INSERT INTO public.appointments VALUES (13, 11, 1, '11:11');
--
-- Data for Name: customers; Type: TABLE DATA; Schema: public; Owner: freecodecamp
--
INSERT INTO public.customers VALUES (11, 'joe1', '1111');
--
-- Data for Name: services; Type: TABLE DATA; Schema: public; Owner: freecodecamp
--
INSERT INTO public.services VALUES (1, 'foot tickling');
INSERT INTO public.services VALUES (2, 'happy ending');
INSERT INTO public.services VALUES (3, 'back rubbing');
--
-- Name: appointments_appointment_id_seq; Type: SEQUENCE SET; Schema: public; Owner: freecodecamp
--
SELECT pg_catalog.setval('public.appointments_appointment_id_seq', 49, true);
--
-- Name: customers_customer_id_seq; Type: SEQUENCE SET; Schema: public; Owner: freecodecamp
--
SELECT pg_catalog.setval('public.customers_customer_id_seq', 41, true);
--
-- Name: services_service_id_seq; Type: SEQUENCE SET; Schema: public; Owner: freecodecamp
--
SELECT pg_catalog.setval('public.services_service_id_seq', 3, true);
--
-- Name: appointments appointments_pkey; Type: CONSTRAINT; Schema: public; Owner: freecodecamp
--
ALTER TABLE ONLY public.appointments
ADD CONSTRAINT appointments_pkey PRIMARY KEY (appointment_id);
--
-- Name: customers customers_phone_key; Type: CONSTRAINT; Schema: public; Owner: freecodecamp
--
ALTER TABLE ONLY public.customers
ADD CONSTRAINT customers_phone_key UNIQUE (phone);
--
-- Name: customers customers_pkey; Type: CONSTRAINT; Schema: public; Owner: freecodecamp
--
ALTER TABLE ONLY public.customers
ADD CONSTRAINT customers_pkey PRIMARY KEY (customer_id);
--
-- Name: services services_pkey; Type: CONSTRAINT; Schema: public; Owner: freecodecamp
--
ALTER TABLE ONLY public.services
ADD CONSTRAINT services_pkey PRIMARY KEY (service_id);
--
-- Name: appointments appointments_customer_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: freecodecamp
--
ALTER TABLE ONLY public.appointments
ADD CONSTRAINT appointments_customer_id_fkey FOREIGN KEY (customer_id) REFERENCES public.customers(customer_id);
--
-- Name: appointments appointments_service_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: freecodecamp
--
ALTER TABLE ONLY public.appointments
ADD CONSTRAINT appointments_service_id_fkey FOREIGN KEY (service_id) REFERENCES public.services(service_id);
--
-- PostgreSQL database dump complete
--
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment