├── .idea ├── .gitignore ├── misc.xml ├── inspectionProfiles │ ├── profiles_settings.xml │ └── Project_Default.xml ├── modules.xml └── pythonProject.iml ├── mainDatabase.db ├── __pycache__ ├── admin.cpython-39.pyc ├── login.cpython-39.pyc ├── database.cpython-39.pyc ├── sessions.cpython-39.pyc └── instructor.cpython-39.pyc ├── main.py ├── README.md ├── login.py ├── database.py ├── instructor.py ├── admin.py └── sessions.py /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /mainDatabase.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HansiKR/Python-tkinter-Project/HEAD/mainDatabase.db -------------------------------------------------------------------------------- /__pycache__/admin.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HansiKR/Python-tkinter-Project/HEAD/__pycache__/admin.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/login.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HansiKR/Python-tkinter-Project/HEAD/__pycache__/login.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/database.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HansiKR/Python-tkinter-Project/HEAD/__pycache__/database.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/sessions.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HansiKR/Python-tkinter-Project/HEAD/__pycache__/sessions.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/instructor.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HansiKR/Python-tkinter-Project/HEAD/__pycache__/instructor.cpython-39.pyc -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/pythonProject.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | import login 3 | 4 | #main method 5 | def main(): 6 | root = Tk() 7 | root.title("DanceFeet Academy") 8 | root.geometry("1400x930+100+50") 9 | root.resizable(False, True) 10 | 11 | #Parsing the root window to the Login class 12 | #Initiating the System 13 | login.Login(root) 14 | 15 | root.mainloop() 16 | 17 | if __name__ == '__main__': 18 | main() 19 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python-tkinter-Project 2 | A small CRUD system for a test Dance Academy using tkinter in Python. 3 | Here, 4 | - Admins can perform CRUD operations on the instructors as well as sessions. 5 | - Instructors can register students to the academy. 6 | - The system will match the requirements of the students with the qualifications of the instructors and suggest a suitable instructor that the admin can then assign to the student. 7 | 8 | Login Screen with default username and password - "admin" 9 | ![Login Screen](https://user-images.githubusercontent.com/109679563/180609856-6cf56f82-6a7a-45f7-91a3-1040f40d6653.png) 10 | 11 | Admin Control Panel to Manage Instructors and Sessions. 12 | ![Admin Panel](https://user-images.githubusercontent.com/109679563/180609851-5b3e2c0c-aada-43bd-8174-d9ffbcd1832f.png) 13 | 14 | CRUD operations allowed to the Admin. 15 | ![Update](https://user-images.githubusercontent.com/109679563/180609845-872d5af5-d177-4ab2-9964-62963bef39be.png) 16 | 17 | Instructor Control Panel 18 | ![Instructor Panel](https://user-images.githubusercontent.com/109679563/180609848-b2983e74-ae67-474b-a7b1-831c7937619d.png) 19 | 20 | Sessions Panel - to match the instructors with the students. (Admin View) 21 | ![Sessions Panel](https://user-images.githubusercontent.com/109679563/180609841-453ac41d-b1f7-4fa1-a119-4e93fd102207.png) 22 | 23 | Sessions Panel - Assigning Instructors 24 | ![Assign Instructor](https://user-images.githubusercontent.com/109679563/180609837-e1c5e928-3f55-4af9-950a-efbb367c130e.png) 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /login.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter import messagebox 3 | import admin 4 | import instructor 5 | from database import Database 6 | 7 | # creating a database object 8 | db = Database("mainDatabase.db") 9 | 10 | 11 | class Login: 12 | def __init__(self, root): 13 | self.root = root 14 | 15 | self.username = StringVar() 16 | self.password = StringVar() 17 | 18 | # Background Color 19 | self.root.config(bg="#5856a0") 20 | 21 | # Call the tkinter frame to the window 22 | self.loginControlFrame() 23 | 24 | """CTA Methods""" 25 | 26 | # login method to redirect to the next frames 27 | def loginFunc(self): 28 | if self.txtUsername.get() == 'admin' and self.txtPassword.get() == 'admin': 29 | self.loginFrame.destroy() 30 | self.rightFrame.destroy() 31 | admin.AdminControls(self.root) 32 | elif db.instructorLogin(self.txtUsername.get(), self.txtPassword.get()): 33 | self.loginFrame.destroy() 34 | self.rightFrame.destroy() 35 | instructor.InstructorControls(self.root) 36 | else: 37 | messagebox.showerror("Error!", "Check your credentials or Please Contact System Admin!") 38 | self.username.set("") 39 | self.password.set("") 40 | 41 | """Login Frame""" 42 | 43 | def loginControlFrame(self): 44 | # Login Frame Configurations 45 | self.loginFrame = Frame(self.root, bg="white") 46 | self.loginFrame.pack(side=LEFT, fill=X, padx=60) 47 | self.login_frame_title = Label(self.loginFrame, text="Login Here", font=("Impact", 35), bg="white", 48 | fg="#5856a0") 49 | self.login_frame_title.grid(row=0, columnspan=2, padx=10, pady=20, sticky="w") 50 | 51 | # Username 52 | self.labelUsername = Label(self.loginFrame, text="Username", font=("Times New Roman", 16, "bold"), bg="white", 53 | fg="#5856a0") 54 | self.labelUsername.grid(row=1, column=0, padx=10, pady=5, sticky="w") 55 | self.txtUsername = Entry(self.loginFrame, textvariable=self.username, font=("Times New Roman", 15), width=30, 56 | bd=5) 57 | self.txtUsername.grid(row=1, column=1, padx=10, pady=5, sticky="w") 58 | 59 | # Password 60 | self.labelPassword = Label(self.loginFrame, text="Password", font=("Times New Roman", 16, "bold"), bg="white", 61 | fg="#5856a0") 62 | self.labelPassword.grid(row=2, column=0, padx=10, pady=5, sticky="w") 63 | self.txtPassword = Entry(self.loginFrame, textvariable=self.password, font=("Times New Roman", 15), width=30, 64 | bd=5, show="*") 65 | self.txtPassword.grid(row=2, column=1, padx=10, pady=5, sticky="w") 66 | 67 | # Login Button 68 | self.btnLogin = Button(self.loginFrame, command=self.loginFunc, text="Login", bd=0, cursor="hand2", 69 | fg="white", bg="#5856a0", width=10, font=("Impact", 15)) 70 | self.btnLogin.grid(row=3, column=1, padx=10, sticky="e") 71 | 72 | # empty label for spacing in grid 73 | self.emptyLabel = Label(self.loginFrame, font=("Times New Roman", 16, "bold"), bg="white", 74 | fg="#5856a0") 75 | self.emptyLabel.grid(row=4, column=1, padx=10, pady=5, sticky="w") 76 | 77 | # Right Side Frame as Welcome Message 78 | self.rightFrame = Frame(self.root, bg="#5856a0") 79 | self.rightFrame.pack(side=RIGHT) 80 | 81 | self.labelCompanyName = Label(self.rightFrame, text="DanceFeet Academy", font=("Goudy Old Style", 55), 82 | bg="#5856a0", 83 | fg="white") 84 | self.labelCompanyName.grid(row=0, column=2, columnspan=2, padx=10) 85 | self.labelDesc = Label(self.rightFrame, text="Enjoy the Art of Dance!", font=("Times New Roman", 25, "italic"), 86 | bg="#5856a0", 87 | fg="white") 88 | self.labelDesc.grid(row=1, column=2, columnspan=2, padx=10, pady=6) 89 | -------------------------------------------------------------------------------- /database.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | 4 | class Database: 5 | def __init__(self, db): 6 | # creating database connection 7 | self.con = sqlite3.connect(db) 8 | self.cur = self.con.cursor() 9 | 10 | # SQL queries to create tables 11 | sql = """ 12 | CREATE TABLE IF NOT EXISTS instructors ( 13 | instructorID Integer PRIMARY KEY, 14 | name text, 15 | gender text, 16 | danceStyles text, 17 | telNo text, 18 | hrRate real, 19 | availability text, 20 | availableDays text, 21 | username text, 22 | password text 23 | ) 24 | """ 25 | sql2 = """ 26 | CREATE TABLE IF NOT EXISTS students ( 27 | studentID Integer PRIMARY KEY, 28 | firstName text, 29 | surName text, 30 | email text, 31 | DOB text, 32 | gender text, 33 | telNo text, 34 | address text 35 | ) 36 | """ 37 | sql3 = """ 38 | CREATE TABLE IF NOT EXISTS sessions ( 39 | sessionID Integer PRIMARY KEY, 40 | studentName text, 41 | danceStyle text, 42 | sessDate text, 43 | sessDay text, 44 | maxRate real, 45 | instructorName text 46 | ) 47 | """ 48 | # cursor executions 49 | self.cur.execute(sql) 50 | self.cur.execute(sql2) 51 | self.cur.execute(sql3) 52 | self.con.commit() 53 | 54 | # local method to hold the dance styles values used across the system 55 | def danceStylesValues(self): 56 | danceStyles = ("Salsa", "Waltz", "HipHop", "Zumba", "Ballet", "Ballroom", "Jazz", "Contemporary") 57 | return danceStyles 58 | 59 | """Admin Controls - Backend""" 60 | 61 | # Add Instructor record to the table 62 | def insertInstructor(self, name, gender, dStyles, telNo, hrRate, avail, days, username, password): 63 | self.cur.execute("INSERT INTO instructors VALUES (NULL,?,?,?,?,?,?,?,?,?)", 64 | (name, gender, dStyles, telNo, hrRate, avail, days, username, password)) 65 | self.con.commit() 66 | 67 | # Display Instructor List from table 68 | def viewInstructor(self): 69 | self.cur.execute("SELECT * FROM instructors") 70 | rows = self.cur.fetchall() 71 | return rows 72 | 73 | # Delete Instructor Entry from table 74 | def removeInstructor(self, insID): 75 | self.cur.execute("DELETE FROM instructors WHERE instructorID=?", (insID,)) 76 | self.con.commit() 77 | 78 | # Edit Instructor Details in the table 79 | def editInstructor(self, insID, name, gender, dStyles, telNo, hrRate, avail, days, username, password): 80 | sql_insert_query = """UPDATE instructors SET name=?, gender=?, danceStyles=?, telNo=?, hrRate=?, availability=?, availableDays=?, username=?, password=? WHERE instructorID=?""" 81 | self.cur.execute(sql_insert_query, 82 | (name, gender, dStyles, telNo, hrRate, avail, days, username, password, insID)) 83 | self.con.commit() 84 | 85 | """instructor Controls - Backend""" 86 | 87 | # Add Student record to the table 88 | def insertStudent(self, firstName, surName, email, dob, gender, telNo, address): 89 | self.cur.execute("INSERT INTO students VALUES (NULL,?,?,?,?,?,?,?)", 90 | (firstName, surName, email, dob, gender, telNo, address)) 91 | self.con.commit() 92 | 93 | # Display Students list from table 94 | def viewStudents(self): 95 | self.cur.execute("SELECT * FROM students") 96 | rows = self.cur.fetchall() 97 | return rows 98 | 99 | # Edit data in the table 100 | def editStudent(self, stuID, firstName, surName, email, dob, gender, telNo, address): 101 | sql_update_query = """UPDATE students SET firstName=?, surName=?, email=?, DOB=?, gender=?, telNo=?, address=? WHERE studentID=?""" 102 | self.cur.execute(sql_update_query, (firstName, surName, email, dob, gender, telNo, address, stuID)) 103 | self.con.commit() 104 | 105 | # Instructor Login Verification - used in the login.py file 106 | def instructorLogin(self, username, password): 107 | sql_select_query = "SELECT * FROM instructors WHERE username=? AND password=?" 108 | self.cur.execute(sql_select_query, (username, password)) 109 | result = self.cur.fetchall() 110 | return result 111 | 112 | """Session Controls - Backend""" 113 | 114 | # Return the full name of the student 115 | def selectStudent(self, stuID): 116 | sql_select_query = "SELECT firstName, surName FROM students WHERE studentID=?" 117 | self.cur.execute(sql_select_query, (stuID,)) 118 | data = self.cur.fetchone() 119 | result = data[0] + " " + data[1] 120 | return result 121 | 122 | # Add new session record to the table 123 | def insertSession(self, stname, dStyles, sessDate, sessDay, maxRate, insName): 124 | self.cur.execute("INSERT INTO sessions VALUES (NULL,?,?,?,?,?,?)", 125 | (stname, dStyles, sessDate, sessDay, maxRate, insName)) 126 | self.con.commit() 127 | 128 | # Display Session List from table 129 | def viewSessionList(self): 130 | self.cur.execute("SELECT * FROM sessions") 131 | rows = self.cur.fetchall() 132 | return rows 133 | 134 | # Update Session Record 135 | def updateSession(self, sessID, stname, dStyles, sessDate, sessDay, maxRate, insName): 136 | sql_update_query = """UPDATE sessions SET studentName=?, danceStyle=?, sessDate=?, sessDay=?, maxRate=?, instructorName=? WHERE sessionID=?""" 137 | self.cur.execute(sql_update_query, (stname, dStyles, sessDate, sessDay, maxRate, insName, sessID)) 138 | self.con.commit() 139 | 140 | # Return suitable instructors list to set the comboBox values 141 | def selectInstructor(self, dStyle, maxRate, sessDay): 142 | sql_select_query = "SELECT name FROM instructors WHERE danceStyles=? AND hrRate<=? AND availableDays LIKE ?" 143 | self.cur.execute(sql_select_query, (dStyle, maxRate, '%' + sessDay + '%')) 144 | namesList = self.cur.fetchall() 145 | result = [] 146 | for i in namesList: 147 | result.append(i[0]) 148 | return result 149 | 150 | # Retrieve Instructor Details from table to display when assigning 151 | def getInstructor(self, insName): 152 | if insName == " ": 153 | return " " 154 | else: 155 | self.cur.execute( 156 | "SELECT name, gender, danceStyles, telNo, hrRate, availableDays FROM instructors WHERE name=?", 157 | (insName,)) 158 | result = self.cur.fetchone() 159 | return result 160 | -------------------------------------------------------------------------------- /instructor.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter import ttk 3 | from database import Database 4 | from tkinter import messagebox 5 | import login 6 | import sessions 7 | from tkcalendar import * 8 | 9 | # creating a database object 10 | db = Database("mainDatabase.db") 11 | 12 | 13 | class InstructorControls: 14 | def __init__(self, root): 15 | self.root = root 16 | 17 | # local variables 18 | self.stuFName = StringVar() 19 | self.stuSurName = StringVar() 20 | self.stuEmail = StringVar() 21 | self.stuGender = StringVar() 22 | self.stuDOB = StringVar() 23 | self.stuTelNo = StringVar() 24 | 25 | # Call the tkinter frames to the window 26 | self.instructorControlsFrame() 27 | self.instructorFrameButtons() 28 | self.tableOutputFrame() 29 | 30 | """Student Info Entries Frame""" 31 | 32 | def instructorControlsFrame(self): 33 | # Instructor Control Frame Configurations 34 | self.entriesFrame = Frame(self.root, bg="#5856a0") 35 | self.entriesFrame.pack(side=TOP, fill=X) 36 | self.instructor_frame_title = Label(self.entriesFrame, text="Instructor Control Panel", 37 | font=("Goudy old style", 35), 38 | bg="#5856a0", 39 | fg="white") 40 | self.instructor_frame_title.grid(row=0, columnspan=2, padx=10, pady=20, sticky="w") 41 | 42 | # Student First Name 43 | self.labelFName = Label(self.entriesFrame, text="First Name", font=("Times New Roman", 16, "bold"), 44 | bg="#5856a0", 45 | fg="white") 46 | self.labelFName.grid(row=1, column=0, padx=10, pady=5, sticky="w") 47 | self.txtFName = Entry(self.entriesFrame, textvariable=self.stuFName, font=("Times New Roman", 15), width=30) 48 | self.txtFName.grid(row=1, column=1, padx=10, pady=5, sticky="w") 49 | 50 | # Student Last Name 51 | self.labelSName = Label(self.entriesFrame, text="Surname", font=("Times New Roman", 16, "bold"), bg="#5856a0", 52 | fg="white") 53 | self.labelSName.grid(row=1, column=2, padx=10, pady=5, sticky="w") 54 | self.txtSName = Entry(self.entriesFrame, textvariable=self.stuSurName, font=("Times New Roman", 15), width=30) 55 | self.txtSName.grid(row=1, column=3, padx=10, pady=5, sticky="w") 56 | 57 | # Student Email 58 | self.labelEmail = Label(self.entriesFrame, text="Email", font=("Times New Roman", 16, "bold"), bg="#5856a0", 59 | fg="white") 60 | self.labelEmail.grid(row=2, column=0, padx=10, pady=5, sticky="w") 61 | self.txtEmail = Entry(self.entriesFrame, textvariable=self.stuEmail, font=("Times New Roman", 15), width=30) 62 | self.txtEmail.grid(row=2, column=1, padx=10, pady=5, sticky="w") 63 | 64 | # Student Gender 65 | self.labelGender = Label(self.entriesFrame, text="Gender", font=("Times New Roman", 16, "bold"), bg="#5856a0", 66 | fg="white") 67 | self.labelGender.grid(row=2, column=2, padx=10, pady=5, sticky="w") 68 | self.comboGender = ttk.Combobox(self.entriesFrame, textvariable=self.stuGender, font=("Times New Roman", 15), 69 | width=28, 70 | state="readonly") 71 | self.comboGender['values'] = ("Male", "Female", "Other", "Prefer Not to Say") 72 | self.comboGender.grid(row=2, column=3, padx=10, pady=5, sticky="w") 73 | 74 | # Student Date of Birth 75 | self.labelDOB = Label(self.entriesFrame, text="Date of Birth", font=("Times New Roman", 16, "bold"), 76 | bg="#5856a0", 77 | fg="white") 78 | self.labelDOB.grid(row=3, column=0, padx=10, pady=5, sticky="w") 79 | self.entryDOB = DateEntry(self.entriesFrame, setmode='day', date_pattern='dd/mm/yyyy', textvariable=self.stuDOB, 80 | font=("Times New Roman", 12), width=35) 81 | self.entryDOB.grid(row=3, column=1, padx=10, pady=5, sticky="w") 82 | 83 | # Student Contact Number 84 | self.labelTelNo = Label(self.entriesFrame, text="Contact Number", font=("Times New Roman", 16, "bold"), 85 | bg="#5856a0", 86 | fg="white") 87 | self.labelTelNo.grid(row=3, column=2, padx=10, pady=5, sticky="w") 88 | self.txtTelNo = Entry(self.entriesFrame, textvariable=self.stuTelNo, font=("Times New Roman", 15), width=30) 89 | self.txtTelNo.grid(row=3, column=3, padx=10, pady=5, sticky="w") 90 | 91 | # Student Address 92 | self.labelAddress = Label(self.entriesFrame, text="Address", font=("Times New Roman", 16, "bold"), bg="#5856a0", 93 | fg="white") 94 | self.labelAddress.grid(row=4, column=0, padx=10, pady=5, sticky="w") 95 | self.txtAddress = Text(self.entriesFrame, font=("Times New Roman", 15), width=82, height=5) 96 | self.txtAddress.grid(row=4, column=1, padx=10, pady=5, sticky="w", columnspan=4) 97 | 98 | """Sub Methods to be used in primary CTA methods""" 99 | 100 | # event trigger Method to display the chosen data from the TreeView back in respective fields 101 | def getData(self, event): 102 | try: 103 | self.selectedRow = self.out.focus() 104 | self.selectedData = self.out.item(self.selectedRow) 105 | self.chosenRow = self.selectedData["values"] 106 | self.stuFName.set(self.chosenRow[1]) 107 | self.stuSurName.set(self.chosenRow[2]) 108 | self.stuEmail.set(self.chosenRow[3]) 109 | self.stuDOB.set(self.chosenRow[4]) 110 | self.stuGender.set(self.chosenRow[5]) 111 | self.stuTelNo.set(self.chosenRow[6]) 112 | self.txtAddress.delete(1.0, END) 113 | self.txtAddress.insert(END, self.chosenRow[7]) 114 | except IndexError as error: 115 | pass 116 | 117 | """CTA Methods""" 118 | 119 | # Method to create a new Student 120 | def regStudent(self): 121 | if self.txtFName.get() == "" or self.txtTelNo.get() == "" or self.txtSName.get() == "" or self.entryDOB.get() == "" or self.txtEmail.get() == "" or self.comboGender.get() == "" or self.txtAddress.get( 122 | 1.0, END) == "": 123 | messagebox.showerror("Error!", "Please fill all the fields!") 124 | return 125 | 126 | db.insertStudent(self.txtFName.get(), self.txtSName.get(), self.txtEmail.get(), self.entryDOB.get(), 127 | self.comboGender.get(), 128 | self.txtTelNo.get(), self.txtAddress.get(1.0, END)) 129 | messagebox.showinfo("Success!", "Record Successfully Insertered!") 130 | self.resetForm() 131 | self.viewStudents() 132 | 133 | # Method to update selected student details 134 | def updateStudent(self): 135 | if self.txtFName.get() == "" or self.txtTelNo.get() == "" or self.txtSName.get() == "" or self.entryDOB.get() == "" or self.txtEmail.get() == "" or self.comboGender.get() == "" or self.txtAddress.get( 136 | 1.0, END) == "": 137 | messagebox.showerror("Error!", "Choose a Student to Update Details!") 138 | return 139 | 140 | db.editStudent(self.chosenRow[0], self.txtFName.get(), self.txtSName.get(), self.txtEmail.get(), 141 | self.entryDOB.get(), 142 | self.comboGender.get(), self.txtTelNo.get(), self.txtAddress.get(1.0, END)) 143 | messagebox.showinfo("Success!", "Record Successfully Updated!") 144 | self.resetForm() 145 | self.viewStudents() 146 | 147 | # Method to display all students in the Treeview Frame 148 | def viewStudents(self): 149 | self.out.delete(*self.out.get_children()) # emptying the table before reloading 150 | for row in db.viewStudents(): 151 | self.out.insert("", END, values=row) 152 | 153 | # Method to direct to the next Frame to Book a Session 154 | def bookSession(self): 155 | try: 156 | self.tempName = db.selectStudent(self.chosenRow[0]) 157 | self.entriesFrame.destroy() 158 | self.buttonsFrame.destroy() 159 | self.tableFrame.destroy() 160 | sessions.BookSession(self.root, self.tempName) 161 | except AttributeError as error: 162 | messagebox.showerror("Error!", "Please View and Select a Student to Book a Session!") 163 | 164 | # Method to reset all input widgets in the frame 165 | def resetForm(self): 166 | self.stuFName.set("") 167 | self.stuSurName.set("") 168 | self.stuGender.set("") 169 | self.stuDOB.set("") 170 | self.stuTelNo.set("") 171 | self.stuEmail.set("") 172 | self.txtAddress.delete(1.0, END) 173 | 174 | # Method to redirect to the login frame 175 | def logOut(self): 176 | self.entriesFrame.destroy() 177 | self.buttonsFrame.destroy() 178 | self.tableFrame.destroy() 179 | login.Login(self.root) 180 | 181 | # CTA Buttons 182 | def instructorFrameButtons(self): 183 | # Button Frame Configurations 184 | self.buttonsFrame = Frame(self.entriesFrame, bg="#5856a0") 185 | self.buttonsFrame.grid(row=9, column=1, padx=10, pady=10, sticky="w", columnspan=8) 186 | 187 | # Add a new Record 188 | self.btnAdd = Button(self.buttonsFrame, command=self.regStudent, text="Register Student", bd=0, cursor="hand2", 189 | bg="#EADDF7", 190 | fg="#5856a0", width=15, font=("Impact", 15)) 191 | self.btnAdd.grid(row=0, column=0, padx=10) 192 | 193 | # Update Selected Record 194 | self.btnUpdate = Button(self.buttonsFrame, command=self.updateStudent, text="Update Student", bd=0, 195 | cursor="hand2", 196 | bg="#EADDF7", 197 | fg="#5856a0", width=15, font=("Impact", 15)) 198 | self.btnUpdate.grid(row=0, column=1, padx=10) 199 | 200 | # Reset Widget Inputs 201 | self.btnReset = Button(self.buttonsFrame, command=self.resetForm, text="Reset Form", bd=0, cursor="hand2", 202 | bg="#EADDF7", fg="#5856a0", width=10, font=("Impact", 15)) 203 | self.btnReset.grid(row=0, column=3, padx=10) 204 | 205 | # Display List 206 | self.btnView = Button(self.buttonsFrame, command=self.viewStudents, text="View Students List", bd=0, 207 | cursor="hand2", 208 | bg="#EADDF7", 209 | fg="#5856a0", width=15, font=("Impact", 15)) 210 | self.btnView.grid(row=0, column=2, padx=10) 211 | 212 | # Book a Session 213 | self.btnBook = Button(self.buttonsFrame, command=self.bookSession, text="Book Session", bd=0, cursor="hand2", 214 | bg="#EADDF7", 215 | fg="#5856a0", width=15, font=("Impact", 15)) 216 | self.btnBook.grid(row=0, column=4, padx=10) 217 | 218 | # LogOut 219 | self.btnLogOut = Button(self.entriesFrame, command=self.logOut, text="Log Out", bd=0, cursor="hand2", 220 | bg="#EADDF7", 221 | fg="#5856a0", width=15, font=("Impact", 15)) 222 | self.btnLogOut.grid(row=0, column=5, padx=20, sticky="e") 223 | 224 | """Table Frame using TreeView""" 225 | 226 | def tableOutputFrame(self): 227 | # Treeview Frame Configurations 228 | self.tableFrame = Frame(self.root, bg="#DADDE6") 229 | self.tableFrame.place(x=0, y=400, width=1400, height=560) 230 | self.yScroll = Scrollbar(self.tableFrame) 231 | self.yScroll.pack(side=RIGHT, fill=Y) 232 | 233 | # ttk style object to add configurations 234 | self.style = ttk.Style() 235 | self.style.configure("mystyle.Treeview", font=('Calibri', 12), 236 | rowheight=70) 237 | self.style.configure("mystyle.Treeview.Heading", font=('Times New Roman', 14, "bold"), sticky="w") 238 | 239 | # Formatting the output table view 240 | self.out = ttk.Treeview(self.tableFrame, yscrollcommand=self.yScroll.set, columns=(1, 2, 3, 4, 5, 6, 7, 8), 241 | style="mystyle.Treeview") 242 | self.out.column("0", width=30) 243 | self.out.heading("1", text="Index") 244 | self.out.heading("2", text="First Name") 245 | self.out.heading("3", text="Last Name") 246 | self.out.heading("4", text="Email") 247 | self.out.column("5", width=80) 248 | self.out.heading("5", text="DOB") 249 | self.out.column("5", width=100) 250 | self.out.heading("6", text="Gender") 251 | self.out.column("6", width=100) 252 | self.out.heading("7", text="Contact Number") 253 | self.out.heading("8", text="Address") 254 | self.out['show'] = 'headings' 255 | 256 | # Virtual Events to trigger methods 257 | self.out.bind("", self.getData) 258 | 259 | # TreeView output layout configurations 260 | self.out.pack(fill=BOTH) 261 | self.yScroll.config(command=self.out.yview) 262 | -------------------------------------------------------------------------------- /admin.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter import ttk 3 | from database import Database 4 | from tkinter import messagebox 5 | import login 6 | import sessions 7 | 8 | # creating a database object 9 | db = Database("mainDatabase.db") 10 | 11 | 12 | class AdminControls: 13 | def __init__(self, root): 14 | self.root = root 15 | 16 | # local variables 17 | self.insName = StringVar() 18 | self.insGender = StringVar() 19 | self.danceStyles = StringVar() 20 | self.insTelNo = StringVar() 21 | self.hrRate = DoubleVar() 22 | self.avail = StringVar() 23 | self.uName = StringVar() 24 | self.pw = StringVar() 25 | 26 | # Days of the week List 27 | self.weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] 28 | 29 | # Call the tkinter frames to the window 30 | self.adminControlsFrame() 31 | self.adminFrameButtons() 32 | self.tableOutputFrame() 33 | 34 | """Instructor Info Entries Frame""" 35 | 36 | def adminControlsFrame(self): 37 | # Admin Control Frame Configurations 38 | self.entriesFrame = Frame(self.root, bg="#5856a0") 39 | self.entriesFrame.pack(side=TOP, fill=X) 40 | self.admin_frame_title = Label(self.entriesFrame, text="Admin Control Panel", font=("Goudy old style", 35), 41 | bg="#5856a0", 42 | fg="white") 43 | self.admin_frame_title.grid(row=0, columnspan=2, padx=10, pady=20, sticky="w") 44 | 45 | # Instructor Name 46 | self.labelName = Label(self.entriesFrame, text="Name", font=("Times New Roman", 16, "bold"), bg="#5856a0", 47 | fg="white") 48 | self.labelName.grid(row=1, column=0, padx=10, pady=5, sticky="w") 49 | self.txtName = Entry(self.entriesFrame, textvariable=self.insName, font=("Times New Roman", 15), width=30) 50 | self.txtName.grid(row=1, column=1, padx=10, pady=5, sticky="w") 51 | 52 | # Instructor Gender 53 | self.labelGender = Label(self.entriesFrame, text="Gender", font=("Times New Roman", 16, "bold"), bg="#5856a0", 54 | fg="white") 55 | self.labelGender.grid(row=1, column=2, padx=10, pady=5, sticky="w") 56 | self.comboGender = ttk.Combobox(self.entriesFrame, textvariable=self.insGender, font=("Times New Roman", 15), 57 | width=28, 58 | state="readonly") 59 | self.comboGender['values'] = ("Male", "Female", "Other", "Prefer Not to Say") 60 | self.comboGender.grid(row=1, column=3, padx=10, pady=5, sticky="w") 61 | 62 | # Instructor Dance Style 63 | self.labelStyles = Label(self.entriesFrame, text="Dance Style", font=("Times New Roman", 16, "bold"), 64 | bg="#5856a0", 65 | fg="white") 66 | self.labelStyles.grid(row=2, column=0, padx=10, pady=5, sticky="w") 67 | self.comboStyle = ttk.Combobox(self.entriesFrame, textvariable=self.danceStyles, font=("Times New Roman", 15), 68 | width=28, 69 | state="readonly") 70 | self.comboStyle['values'] = db.danceStylesValues() 71 | self.comboStyle.grid(row=2, column=1, padx=10, pady=5, sticky="w") 72 | 73 | # Instructor Tel No 74 | self.labelTelNo = Label(self.entriesFrame, text="Contact Number", font=("Times New Roman", 16, "bold"), 75 | bg="#5856a0", 76 | fg="white") 77 | self.labelTelNo.grid(row=2, column=2, padx=10, pady=5, sticky="w") 78 | self.txtTelNo = Entry(self.entriesFrame, textvariable=self.insTelNo, font=("Times New Roman", 15), width=30) 79 | self.txtTelNo.grid(row=2, column=3, padx=10, pady=5, sticky="w") 80 | 81 | # Instructor Hourly Rate 82 | self.labelhrRate = Label(self.entriesFrame, text="Hourly Rate", font=("Times New Roman", 16, "bold"), 83 | bg="#5856a0", 84 | fg="white") 85 | self.labelhrRate.grid(row=3, column=0, padx=10, pady=5, sticky="w") 86 | self.txthrRate = Entry(self.entriesFrame, textvariable=self.hrRate, font=("Times New Roman", 15), width=30) 87 | self.txthrRate.grid(row=3, column=1, padx=10, pady=5, sticky="w") 88 | 89 | # Instructor Availability 90 | self.labelAvail = Label(self.entriesFrame, text="Availability", font=("Times New Roman", 16, "bold"), 91 | bg="#5856a0", 92 | fg="white") 93 | self.labelAvail.grid(row=3, column=2, padx=10, pady=5, sticky="w") 94 | self.comboAvail = ttk.Combobox(self.entriesFrame, textvariable=self.avail, font=("Times New Roman", 15), 95 | width=28, 96 | state="readonly") 97 | self.comboAvail['values'] = ("AVAILABLE", "NOT AVAILABLE") 98 | self.comboAvail.grid(row=3, column=3, padx=10, pady=5, sticky="w") 99 | 100 | # Instructor Working Days 101 | self.labelListDays = Label(self.entriesFrame, text="Choose Available Days", 102 | font=("Times New Roman", 16, "bold"), 103 | bg="#5856a0", 104 | fg="white") 105 | self.labelListDays.grid(row=4, column=2, padx=10, pady=5, sticky="w") 106 | self.listDays = Listbox(self.entriesFrame, selectmode=MULTIPLE, font=("Times New Roman", 10), width=50, 107 | height=7) 108 | self.listDays.grid(row=4, column=3, columnspan=3, rowspan=6, padx=10, pady=5, sticky="w") 109 | 110 | # Instructor Username 111 | self.labelUsername = Label(self.entriesFrame, text="Username", font=("Times New Roman", 16, "bold"), 112 | bg="#5856a0", 113 | fg="white") 114 | self.labelUsername.grid(row=4, column=0, padx=10, pady=5, sticky="w") 115 | self.txtUsername = Entry(self.entriesFrame, textvariable=self.uName, font=("Times New Roman", 15), width=30, 116 | bg="#D3D3E7") 117 | self.txtUsername.grid(row=4, column=1, padx=10, pady=5, sticky="w") 118 | 119 | # Instructor Password 120 | self.labelPassword = Label(self.entriesFrame, text="Password", font=("Times New Roman", 16, "bold"), 121 | bg="#5856a0", 122 | fg="white") 123 | self.labelPassword.grid(row=5, column=0, padx=10, pady=5, sticky="w") 124 | self.txtPassword = Entry(self.entriesFrame, textvariable=self.pw, font=("Times New Roman", 15), width=30, 125 | bg="#D3D3E7") 126 | self.txtPassword.grid(row=5, column=1, padx=10, pady=5, sticky="w") 127 | 128 | """Sub Methods to be used in primary CTA methods""" 129 | 130 | # event trigger Method to display the chosen data from the TreeView back in respective fields 131 | def getData(self, event): 132 | try: 133 | self.selectedRow = self.out.focus() 134 | self.selectedData = self.out.item(self.selectedRow) 135 | self.chosenRow = self.selectedData["values"] 136 | self.insName.set(self.chosenRow[1]) 137 | self.insGender.set(self.chosenRow[2]) 138 | self.danceStyles.set(self.chosenRow[3]) 139 | self.insTelNo.set(self.chosenRow[4]) 140 | self.hrRate.set(self.chosenRow[5]) 141 | self.avail.set(self.chosenRow[6]) 142 | self.selectDays(event) 143 | self.uName.set(self.chosenRow[8]) 144 | self.pw.set(self.chosenRow[9]) 145 | except IndexError as error: 146 | pass 147 | 148 | # Event trigger method to display the weekdays depending on the comboBox value 149 | def selectDays(self, event): 150 | if self.comboAvail.get() == "NOT AVAILABLE": 151 | self.listDays.delete(0, END) 152 | else: 153 | self.listDays.delete(0, END) # clearing existing entries before inserting 154 | for day in self.weekdays: 155 | self.listDays.insert(END, day) 156 | 157 | # Method to get the selected (available) days from the ListBox Widget 158 | def getAvailableDays(self): 159 | self.availDays = [] 160 | for day in self.listDays.curselection(): 161 | # creating a string list from the chosen list indexes 162 | self.availDays.append(str(self.listDays.get(day))) 163 | return self.availDays 164 | 165 | """CTA Methods""" 166 | 167 | # Method to create a new Instructor 168 | def addInstructor(self): 169 | if self.txtName.get() == "" or self.txtTelNo.get() == "" or self.comboAvail.get() == "" or self.comboStyle.get() == "" or self.txthrRate.get() == "" or self.comboGender.get() == "" or self.txtUsername.get() == "" or self.txtPassword.get() == "": 170 | messagebox.showerror("Error!", "Please fill all the fields!") 171 | return 172 | 173 | self.tempAvailDays = ', '.join(self.getAvailableDays()) # converting the list of Days into a string 174 | 175 | db.insertInstructor(self.txtName.get(), self.comboGender.get(), self.comboStyle.get(), self.txtTelNo.get(), 176 | self.txthrRate.get(), self.comboAvail.get(), self.tempAvailDays, 177 | self.txtUsername.get(), self.txtPassword.get()) 178 | messagebox.showinfo("Success!", "Record Successfully Insertered!") 179 | self.resetForm() 180 | self.viewInstructor() 181 | 182 | # Method to update selected Instructor details 183 | def assignInstructor(self): 184 | if self.txtName.get() == "" or self.txtTelNo.get() == "" or self.comboAvail.get() == "" or self.comboStyle.get() == "" or self.txthrRate.get() == "" or self.comboGender.get() == "" or self.txtUsername.get() == "" or self.txtPassword.get() == "": 185 | messagebox.showerror("Error!", "Choose an Instructor to Update Details!") 186 | return 187 | 188 | self.tempAvailDays = ', '.join(self.getAvailableDays()) # converting the list of Days into a string 189 | 190 | try: 191 | db.editInstructor(self.chosenRow[0], self.txtName.get(), self.comboGender.get(), self.comboStyle.get(), 192 | self.txtTelNo.get(), 193 | self.txthrRate.get(), self.comboAvail.get(), self.tempAvailDays, 194 | self.txtUsername.get(), self.txtPassword.get()) 195 | messagebox.showinfo("Success!", "Record Successfully Updated!") 196 | self.resetForm() 197 | self.viewInstructor() 198 | except AttributeError as error: 199 | messagebox.showerror("Error!", "Choose an existing Instructor to Update Details") 200 | 201 | # Method to remove selected instructor from the database 202 | def dltInstructor(self): 203 | try: 204 | db.removeInstructor(self.chosenRow[0]) 205 | self.resetForm() 206 | self.viewInstructor() 207 | except AttributeError as error: 208 | messagebox.showerror("Error!", "Please Choose an Instructor Record to Remove!") 209 | 210 | # Method to display all instructors in the Treeview Frame 211 | def viewInstructor(self): 212 | self.out.delete(*self.out.get_children()) # emptying the table before reloading 213 | for row in db.viewInstructor(): 214 | self.out.insert("", END, values=row) 215 | 216 | # Method to direct to the next Frame to Assign Instructors 217 | def manageSessions(self): 218 | self.entriesFrame.destroy() 219 | self.buttonsFrame.destroy() 220 | self.tableFrame.destroy() 221 | sessions.AssignSession(self.root) 222 | 223 | # Method to reset all input widgets in the frame 224 | def resetForm(self): 225 | self.insName.set("") 226 | self.insGender.set("") 227 | self.danceStyles.set("") 228 | self.insTelNo.set("") 229 | self.hrRate.set("") 230 | self.avail.set("") 231 | self.listDays.delete(0, END) 232 | self.uName.set("") 233 | self.pw.set("") 234 | 235 | # Method to redirect to the login frame 236 | def logOut(self): 237 | self.entriesFrame.destroy() 238 | self.buttonsFrame.destroy() 239 | self.tableFrame.destroy() 240 | login.Login(self.root) 241 | 242 | """CTA Buttons Frame""" 243 | 244 | def adminFrameButtons(self): 245 | # Button Frame Configurations 246 | self.buttonsFrame = Frame(self.entriesFrame, bg="#5856a0") 247 | self.buttonsFrame.grid(row=10, column=0, padx=10, pady=10, sticky="w", columnspan=8) 248 | 249 | # Add a new Record 250 | self.btnAdd = Button(self.buttonsFrame, command=self.addInstructor, text="Add Instructor", bd=0, cursor="hand2", 251 | bg="#EADDF7", 252 | fg="#5856a0", width=20, font=("Impact", 15)) 253 | self.btnAdd.grid(row=0, column=0, padx=10) 254 | 255 | # Update Selected Record 256 | self.btnUpdate = Button(self.buttonsFrame, command=self.assignInstructor, text="Update Instructor", bd=0, 257 | cursor="hand2", 258 | bg="#EADDF7", 259 | fg="#5856a0", width=20, font=("Impact", 15)) 260 | self.btnUpdate.grid(row=0, column=1, padx=10) 261 | 262 | # Delete Selected Record 263 | self.btnDlt = Button(self.buttonsFrame, command=self.dltInstructor, text="Remove Instructor", bd=0, 264 | cursor="hand2", 265 | bg="#EADDF7", 266 | fg="#5856a0", width=20, font=("Impact", 15)) 267 | self.btnDlt.grid(row=0, column=2, padx=10) 268 | 269 | # Reset Widget Inputs 270 | self.btnReset = Button(self.buttonsFrame, command=self.resetForm, text="Reset Form", bd=0, cursor="hand2", 271 | bg="#EADDF7", fg="#5856a0", width=20, font=("Impact", 15)) 272 | self.btnReset.grid(row=0, column=3, padx=10) 273 | 274 | # Display List 275 | self.btnView = Button(self.buttonsFrame, command=self.viewInstructor, text="View Instructor List", bd=0, 276 | cursor="hand2", 277 | bg="#EADDF7", 278 | fg="#5856a0", width=20, font=("Impact", 15)) 279 | self.btnView.grid(row=0, column=4, padx=10) 280 | 281 | # Manage Sessions 282 | self.btnManageSess = Button(self.buttonsFrame, command=self.manageSessions, text="Manage Sessions", bd=0, 283 | cursor="hand2", 284 | bg="#EADDF7", fg="#5856a0", width=20, font=("Impact", 15)) 285 | self.btnManageSess.grid(row=0, column=5, padx=10) 286 | 287 | # LogOut 288 | self.btnLogOut = Button(self.entriesFrame, command=self.logOut, text="Log Out", bd=0, cursor="hand2", 289 | bg="#EADDF7", 290 | fg="#5856a0", width=15, font=("Impact", 15)) 291 | self.btnLogOut.grid(row=0, column=6, padx=15, sticky="e") 292 | 293 | """Table Frame using TreeView""" 294 | 295 | def tableOutputFrame(self): 296 | # Treeview Frame Configurations 297 | self.tableFrame = Frame(self.root, bg="#DADDE6") 298 | self.tableFrame.place(x=0, y=400, width=1400, height=560) 299 | self.yScroll = Scrollbar(self.tableFrame) 300 | self.yScroll.pack(side=RIGHT, fill=Y) 301 | 302 | # ttk style object to add configurations 303 | self.style = ttk.Style() 304 | self.style.configure("mystyle.Treeview", font=('Calibri', 12), 305 | rowheight=50) 306 | self.style.configure("mystyle.Treeview.Heading", font=('Times New Roman', 14, "bold"), sticky="w") 307 | 308 | # Formatting the output table view 309 | self.out = ttk.Treeview(self.tableFrame, yscrollcommand=self.yScroll.set, 310 | columns=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), style="mystyle.Treeview") 311 | self.out.heading("1", text="Index") 312 | self.out.column("1", width=10) 313 | self.out.heading("2", text="Name") 314 | self.out.column("2", width=30) 315 | self.out.heading("3", text="Gender") 316 | self.out.column("3", width=5) 317 | self.out.heading("4", text="Dance Styles") 318 | self.out.column("4", width=8) 319 | self.out.heading("5", text="Tel Number") 320 | self.out.column("5", width=10) 321 | self.out.heading("6", text="Hourly Rate") 322 | self.out.column("6", width=6) 323 | self.out.heading("7", text="Availability") 324 | self.out.column("7", width=5) 325 | self.out.heading("8", text="Available Days") 326 | self.out.heading("9", text="Username") 327 | self.out.column("9", width=3) 328 | self.out.heading("10", text="Password") 329 | self.out.column("10", width=3) 330 | self.out['show'] = 'headings' 331 | 332 | # Virtual Events to trigger methods 333 | self.out.bind("", self.getData) 334 | self.comboAvail.bind("<>", self.selectDays) 335 | 336 | # TreeView output layout configurations 337 | self.out.pack(fill=X) 338 | self.yScroll.config(command=self.out.yview) 339 | -------------------------------------------------------------------------------- /sessions.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter import ttk 3 | from tkcalendar import * 4 | from datetime import * 5 | import admin 6 | import instructor 7 | from database import Database 8 | from tkinter import messagebox 9 | 10 | # creating a database object 11 | db = Database("mainDatabase.db") 12 | 13 | 14 | class BookSession: 15 | def __init__(self, root, stname): 16 | self.root = root 17 | self.tempName = stname 18 | 19 | # local variables 20 | self.studentName = StringVar() 21 | self.danceStyle = StringVar() 22 | self.sessDate = StringVar() 23 | self.sessDay = StringVar() 24 | self.maxRate = DoubleVar() 25 | 26 | # automatically set the student name when making bookings 27 | self.studentName.set(self.tempName) 28 | 29 | # Call the tkinter frames to the window 30 | self.instructorSessionsFrame() 31 | self.sessionsFrameButtons() 32 | self.tableOutputFrame() 33 | 34 | """Session Details Frame""" 35 | 36 | def instructorSessionsFrame(self): 37 | # Instructor Sessions Frame Configurations 38 | self.sessionFrame = Frame(self.root, bg="#5856a0") 39 | self.sessionFrame.pack(side=TOP, fill=X) 40 | self.session_frame_title = Label(self.sessionFrame, text="Session Control Panel", font=("Goudy old style", 35), 41 | bg="#5856a0", 42 | fg="white") 43 | self.session_frame_title.grid(row=0, columnspan=2, padx=10, pady=20, sticky="w") 44 | 45 | # Student Full Name 46 | self.labelStName = Label(self.sessionFrame, text="Student Name", font=("Times New Roman", 16, "bold"), 47 | bg="#5856a0", 48 | fg="white") 49 | self.labelStName.grid(row=1, column=0, padx=10, pady=5, sticky="w") 50 | self.txtStName = Entry(self.sessionFrame, textvariable=self.studentName, font=("Times New Roman", 15), width=30, 51 | state="readonly") 52 | self.txtStName.grid(row=1, column=1, padx=10, pady=5, sticky="w") 53 | 54 | # Session Date 55 | self.labelSessDate = Label(self.sessionFrame, text="Session Date", font=("Times New Roman", 16, "bold"), 56 | bg="#5856a0", 57 | fg="white") 58 | self.labelSessDate.grid(row=2, column=0, padx=10, pady=5, sticky="w") 59 | self.entrySessDate = DateEntry(self.sessionFrame, setmode='day', date_pattern='dd/mm/yyyy', 60 | textvariable=self.sessDate, mindate=datetime.now(), font=("Times New Roman", 12), 61 | width=35) 62 | self.entrySessDate.grid(row=2, column=1, padx=10, pady=5, sticky="w") 63 | 64 | # Session Day 65 | self.labelSessDay = Label(self.sessionFrame, text="Session Day", font=("Times New Roman", 16, "bold"), 66 | bg="#5856a0", 67 | fg="white") 68 | self.labelSessDay.grid(row=3, column=0, padx=10, pady=5, sticky="w") 69 | self.entrySessDay = Entry(self.sessionFrame, textvariable=self.sessDay, font=("Times New Roman", 15), width=30, 70 | state="readonly") 71 | self.entrySessDay.grid(row=3, column=1, padx=10, pady=5, sticky="w") 72 | 73 | # Student Dance Style 74 | self.labelStyle = Label(self.sessionFrame, text="Dance Style", font=("Times New Roman", 16, "bold"), 75 | bg="#5856a0", 76 | fg="white") 77 | self.labelStyle.grid(row=4, column=0, padx=10, pady=5, sticky="w") 78 | self.comboStyle = ttk.Combobox(self.sessionFrame, textvariable=self.danceStyle, font=("Times New Roman", 15), 79 | width=28, 80 | state="readonly") 81 | self.comboStyle['values'] = db.danceStylesValues() 82 | self.comboStyle.grid(row=4, column=1, padx=10, pady=5, sticky="w") 83 | 84 | # Student's Max Rate Payable 85 | self.labelMaxRate = Label(self.sessionFrame, text="Max Rate", font=("Times New Roman", 16, "bold"), 86 | bg="#5856a0", 87 | fg="white") 88 | self.labelMaxRate.grid(row=5, column=0, padx=10, pady=5, sticky="w") 89 | self.txtMaxRate = Entry(self.sessionFrame, textvariable=self.maxRate, font=("Times New Roman", 15), width=30) 90 | self.txtMaxRate.grid(row=5, column=1, padx=10, pady=5, sticky="w") 91 | 92 | """Sub Methods to be used in primary CTA methods""" 93 | 94 | # event trigger Method to display the chosen data from the TreeView back in respective fields 95 | def getData(self, event): 96 | try: 97 | self.selectedRow = self.out.focus() 98 | self.selectedData = self.out.item(self.selectedRow) 99 | self.chosenRow = self.selectedData["values"] 100 | self.studentName.set(self.chosenRow[1]) 101 | self.danceStyle.set(self.chosenRow[2]) 102 | self.sessDate.set(self.chosenRow[3]) 103 | self.sessDay.set(self.chosenRow[4]) 104 | self.maxRate.set(self.chosenRow[5]) 105 | except IndexError as error: 106 | pass 107 | 108 | # Method to redirect to the previous frame 109 | def GoBack(self): 110 | self.sessionFrame.destroy() 111 | self.buttonsFrame.destroy() 112 | self.tableFrame.destroy() 113 | instructor.InstructorControls(self.root) 114 | 115 | # getting the selected weekday by creating a datetime object from the str variable 116 | def getDay(self, event): 117 | weekDayObj = datetime.strptime(self.entrySessDate.get(), '%d/%m/%Y') 118 | weekday = weekDayObj.strftime('%A') 119 | self.sessDay.set(weekday) 120 | 121 | """CTA Methods""" 122 | 123 | # Method to create a new session 124 | def addSession(self): 125 | if self.txtStName.get() == "" or self.comboStyle.get() == "" or self.entrySessDate.get() == "" or self.txtMaxRate.get() == "": 126 | messagebox.showerror("Error!", "Please fill all the fields!") 127 | return 128 | 129 | db.insertSession(self.txtStName.get(), self.comboStyle.get(), self.entrySessDate.get(), self.sessDay.get(), 130 | self.txtMaxRate.get(), " ") 131 | messagebox.showinfo("Success!", "Session Successfully Booked!") 132 | self.viewSessions() 133 | 134 | # Method to view all sessions 135 | def viewSessions(self): 136 | self.out.delete(*self.out.get_children()) # emptying the treeview before reloading 137 | for row in db.viewSessionList(): 138 | self.out.insert("", END, values=row) 139 | 140 | # Method to update the chosen Session Details 141 | def updateSession(self): 142 | if self.txtStName.get() == "" or self.comboStyle.get() == "" or self.entrySessDate.get() == "" or self.txtMaxRate.get() == "": 143 | messagebox.showerror("Error!", "Please a Session to Update Details!") 144 | return 145 | 146 | db.updateSession(self.chosenRow[0], self.txtStName.get(), self.comboStyle.get(), self.entrySessDate.get(), 147 | self.sessDay.get(), 148 | self.txtMaxRate.get(), " ") 149 | messagebox.showinfo("Success!", "Session Details Successfully Updated!") 150 | self.viewSessions() 151 | 152 | """CTA Buttons Frame""" 153 | 154 | def sessionsFrameButtons(self): 155 | # Session Buttons Frame Configurations 156 | self.buttonsFrame = Frame(self.sessionFrame, bg="#5856a0") 157 | self.buttonsFrame.grid(row=7, column=0, padx=10, pady=10, sticky="w", columnspan=8) 158 | 159 | # Add new session 160 | self.btnAddSession = Button(self.buttonsFrame, command=self.addSession, text="Add Session", bd=0, 161 | cursor="hand2", 162 | bg="#EADDF7", 163 | fg="#5856a0", width=20, font=("Impact", 15)) 164 | self.btnAddSession.grid(row=0, column=0, padx=10) 165 | 166 | # View all existing session bookings 167 | self.btnViewSessions = Button(self.buttonsFrame, command=self.viewSessions, text="View Sessions List", bd=0, 168 | cursor="hand2", 169 | bg="#EADDF7", 170 | fg="#5856a0", width=20, font=("Impact", 15)) 171 | self.btnViewSessions.grid(row=0, column=1, padx=10) 172 | 173 | # Update selected session details 174 | self.btnUpdateSessions = Button(self.buttonsFrame, command=self.updateSession, text="Update Session Details", 175 | bd=0, 176 | cursor="hand2", 177 | bg="#EADDF7", 178 | fg="#5856a0", width=20, font=("Impact", 15)) 179 | self.btnUpdateSessions.grid(row=0, column=2, padx=10) 180 | 181 | # GoBack 182 | self.btnGoBack = Button(self.sessionFrame, command=self.GoBack, text="Go Back", bd=0, cursor="hand2", 183 | bg="#EADDF7", 184 | fg="#5856a0", width=15, font=("Impact", 15)) 185 | self.btnGoBack.grid(row=0, column=2, padx=10, sticky="e") 186 | 187 | """Table Frame using TreeView""" 188 | 189 | def tableOutputFrame(self): 190 | # Treeview Frame Configurations 191 | self.tableFrame = Frame(self.root, bg="#DADDE6") 192 | self.tableFrame.place(x=0, y=400, width=1400, height=560) 193 | self.yScroll = Scrollbar(self.tableFrame) 194 | self.yScroll.pack(side=RIGHT, fill=Y) 195 | 196 | # ttk style object to add configurations 197 | self.style = ttk.Style() 198 | self.style.configure("mystyle.Treeview", font=('Calibri', 12), 199 | rowheight=50) 200 | self.style.configure("mystyle.Treeview.Heading", font=('Times New Roman', 14, "bold"), sticky="w") 201 | 202 | # Formatting the output table view 203 | self.out = ttk.Treeview(self.tableFrame, yscrollcommand=self.yScroll.set, columns=(1, 2, 3, 4, 5, 6, 7), 204 | style="mystyle.Treeview") 205 | self.out.heading("1", text="Session Index") 206 | self.out.column("1", width=5) 207 | self.out.heading("2", text="Student Name") 208 | self.out.heading("3", text="Dance Style") 209 | self.out.column("3", width=20) 210 | self.out.heading("4", text="Session Date") 211 | self.out.column("4", width=5) 212 | self.out.heading("5", text="Booked Day") 213 | self.out.column("5", width=5) 214 | self.out.heading("6", text="Max Rate") 215 | self.out.column("6", width=5) 216 | self.out.heading("7", text="Instructor Name") 217 | self.out.column("7", width=15) 218 | self.out['show'] = 'headings' 219 | 220 | # Virtual Events to trigger methods 221 | self.out.bind("", self.getData) 222 | self.entrySessDate.bind("<>", self.getDay) 223 | 224 | # TreeView output layout configurations 225 | self.out.pack(fill=X) 226 | self.yScroll.config(command=self.out.yview) 227 | 228 | 229 | # Assignining Instructors 230 | class AssignSession: 231 | def __init__(self, root): 232 | self.root = root 233 | 234 | # local variables 235 | self.studentName = StringVar() 236 | self.danceStyle = StringVar() 237 | self.sessDate = StringVar() 238 | self.sessDay = StringVar() 239 | self.maxRate = DoubleVar() 240 | self.instructorName = StringVar() 241 | 242 | # Call the tkinter frames to the window 243 | self.sessionsFrame() 244 | self.sessionFrameButtons() 245 | self.tableOutputFrame() 246 | 247 | """Session Details Frame""" 248 | 249 | def sessionsFrame(self): 250 | # Admin Sessions Frame Configurations 251 | self.sessionFrame = Frame(self.root, bg="#5856a0") 252 | self.sessionFrame.pack(side=TOP, fill=X) 253 | self.session_frame_title = Label(self.sessionFrame, text="Session Control Panel", font=("Goudy old style", 35), 254 | bg="#5856a0", 255 | fg="white") 256 | self.session_frame_title.grid(row=0, columnspan=2, padx=10, pady=20, sticky="w") 257 | 258 | # Student Full Name 259 | self.labelStName = Label(self.sessionFrame, text="Student Name", font=("Times New Roman", 16, "bold"), 260 | bg="#5856a0", 261 | fg="white") 262 | self.labelStName.grid(row=1, column=0, padx=10, pady=5, sticky="w") 263 | self.txtStName = Entry(self.sessionFrame, textvariable=self.studentName, font=("Times New Roman", 15), width=30, 264 | state="readonly") 265 | self.txtStName.grid(row=1, column=1, padx=10, pady=5, sticky="w") 266 | 267 | # Session Date 268 | self.labelSessDate = Label(self.sessionFrame, text="Session Date", font=("Times New Roman", 16, "bold"), 269 | bg="#5856a0", 270 | fg="white") 271 | self.labelSessDate.grid(row=2, column=0, padx=10, pady=5, sticky="w") 272 | self.txtSessDate = Entry(self.sessionFrame, textvariable=self.sessDate, font=("Times New Roman", 15), width=30, 273 | state="readonly") 274 | self.txtSessDate.grid(row=2, column=1, padx=10, pady=5, sticky="w") 275 | 276 | # Session Day 277 | self.labelSessDay = Label(self.sessionFrame, text="Session Day", font=("Times New Roman", 16, "bold"), 278 | bg="#5856a0", 279 | fg="white") 280 | self.labelSessDay.grid(row=3, column=0, padx=10, pady=5, sticky="w") 281 | self.entrySessDay = Entry(self.sessionFrame, textvariable=self.sessDay, font=("Times New Roman", 15), width=30, 282 | state="readonly") 283 | self.entrySessDay.grid(row=3, column=1, padx=10, pady=5, sticky="w") 284 | 285 | # Student Dance Style 286 | self.labelStyle = Label(self.sessionFrame, text="Dance Style", font=("Times New Roman", 16, "bold"), 287 | bg="#5856a0", 288 | fg="white") 289 | self.labelStyle.grid(row=4, column=0, padx=10, pady=5, sticky="w") 290 | self.comboStyle = ttk.Combobox(self.sessionFrame, textvariable=self.danceStyle, font=("Times New Roman", 15), 291 | width=28, state="disabled") 292 | self.comboStyle.grid(row=4, column=1, padx=10, pady=5, sticky="w") 293 | 294 | # Student's Max Rate Payable 295 | self.labelMaxRate = Label(self.sessionFrame, text="Max Rate", font=("Times New Roman", 16, "bold"), 296 | bg="#5856a0", 297 | fg="white") 298 | self.labelMaxRate.grid(row=5, column=0, padx=10, pady=5, sticky="w") 299 | self.txtMaxRate = Entry(self.sessionFrame, textvariable=self.maxRate, font=("Times New Roman", 15), width=30, 300 | state="readonly") 301 | self.txtMaxRate.grid(row=5, column=1, padx=10, pady=5, sticky="w") 302 | 303 | # Available Instructor List 304 | self.labelInsName = Label(self.sessionFrame, text="Instructor Name", font=("Times New Roman", 16, "bold"), 305 | bg="#5856a0", 306 | fg="white") 307 | self.labelInsName.grid(row=6, column=0, padx=10, pady=5, sticky="w") 308 | self.comboInsName = ttk.Combobox(self.sessionFrame, textvariable=self.instructorName, 309 | font=("Times New Roman", 15), width=28, 310 | state="readonly") 311 | self.comboInsName['values'] = ("-") 312 | self.comboInsName.grid(row=6, column=1, padx=10, pady=5, sticky="w") 313 | 314 | # Label to Display Instructor Details when assigning 315 | self.labelDetails = Label(self.sessionFrame, text="Instructor Details:", font=("Times New Roman", 16, "bold"), 316 | bg="#5856a0", 317 | fg="white") 318 | self.labelDetails.grid(row=1, column=3, padx=10, pady=5, sticky="w") 319 | self.labelTxtDetails = Label(self.sessionFrame, text=" ", 320 | font=("Helvetica", 15), justify=LEFT, 321 | bg="white", 322 | fg="#5856a0", width=75, height=10, anchor="w") 323 | self.labelTxtDetails.grid(row=2, column=3, padx=10, pady=5, sticky="w", columnspan=4, rowspan=6) 324 | 325 | """Sub Methods to be used in primary CTA methods""" 326 | 327 | # event trigger Method to display the chosen data from the TreeView back in respective fields 328 | def getData(self, event): 329 | try: 330 | self.selectedRow = self.out.focus() 331 | self.selectedData = self.out.item(self.selectedRow) 332 | self.chosenRow = self.selectedData["values"] 333 | self.studentName.set(self.chosenRow[1]) 334 | self.danceStyle.set(self.chosenRow[2]) 335 | self.sessDate.set(self.chosenRow[3]) 336 | self.sessDay.set(self.chosenRow[4]) 337 | self.maxRate.set(self.chosenRow[5]) 338 | self.instructorName.set(self.chosenRow[6]) 339 | self.displayInsDetails(event) 340 | except IndexError as error: 341 | pass 342 | 343 | # Method to display instructor names depending on the chosen session details 344 | def comboBoxValues(self, event): 345 | self.selected = self.out.focus() 346 | self.chosenData = self.out.item(self.selected, 'values') 347 | global instructorList 348 | # Parsing the style, maxRate, session Day values for querying the db 349 | instructorList = db.selectInstructor(self.chosenData[2], float(self.chosenData[5]), self.chosenData[4]) 350 | self.comboInsName['values'] = instructorList 351 | 352 | # Method to Display Instructor Details when assigning 353 | def displayInsDetails(self, event): 354 | detailRecord = db.getInstructor(self.comboInsName.get()) 355 | if detailRecord == " ": 356 | self.labelTxtDetails.config(text=" ") 357 | else: 358 | recordString = ' Name: {} \n Gender: {} \n Dance Style: {}\n Contact No: {}\n Hourly Rate: {}\n Available Days: {}'.format( 359 | *detailRecord) 360 | self.labelTxtDetails.config(text=recordString) 361 | 362 | # Method to redirect to the previous frame 363 | def GoBack(self): 364 | self.sessionFrame.destroy() 365 | self.buttonsFrame.destroy() 366 | self.tableFrame.destroy() 367 | admin.AdminControls(self.root) 368 | 369 | """CTA Methods""" 370 | 371 | # Method to view all sessions 372 | def viewSessions(self): 373 | self.out.delete(*self.out.get_children()) # emptying the table before reloading 374 | for row in db.viewSessionList(): 375 | self.out.insert("", END, values=row) 376 | 377 | # Method to assign an instructor to the chosen session 378 | def assignInstructor(self): 379 | if self.txtStName.get() == "" or self.comboStyle.get() == "" or self.txtSessDate.get() == "" or self.txtMaxRate.get() == "" or self.comboInsName.get() == "": 380 | messagebox.showerror("Error!", "Please choose an instructor!") 381 | return 382 | 383 | db.updateSession(self.chosenRow[0], self.txtStName.get(), self.comboStyle.get(), self.txtSessDate.get(), 384 | self.sessDay.get(), 385 | self.txtMaxRate.get(), 386 | self.comboInsName.get()) 387 | messagebox.showinfo("Success!", "Instructor Successfully Assigned!") 388 | self.viewSessions() 389 | 390 | """CTA Buttons Frame""" 391 | 392 | def sessionFrameButtons(self): 393 | # Session Buttons Frame Configurations 394 | self.buttonsFrame = Frame(self.sessionFrame, bg="#5856a0") 395 | self.buttonsFrame.grid(row=7, column=0, padx=10, pady=10, sticky="w", columnspan=8) 396 | 397 | # Assign Instructor to chosen session 398 | self.btnAssignInstructor = Button(self.buttonsFrame, command=self.assignInstructor, text="Assign Instructor", 399 | bd=0, 400 | cursor="hand2", 401 | bg="#EADDF7", 402 | fg="#5856a0", width=20, font=("Impact", 15)) 403 | self.btnAssignInstructor.grid(row=0, column=0, padx=10) 404 | 405 | # View all existing session bookings 406 | self.btnViewSessions = Button(self.buttonsFrame, command=self.viewSessions, text="View Sessions List", bd=0, 407 | cursor="hand2", 408 | bg="#EADDF7", 409 | fg="#5856a0", width=20, font=("Impact", 15)) 410 | self.btnViewSessions.grid(row=0, column=1, padx=10) 411 | 412 | # GoBack 413 | self.btnGoBack = Button(self.sessionFrame, command=self.GoBack, text="Go Back", bd=0, cursor="hand2", 414 | bg="#EADDF7", 415 | fg="#5856a0", width=15, font=("Impact", 15)) 416 | self.btnGoBack.grid(row=0, column=6, padx=10, sticky="e") 417 | 418 | """Table Frame using TreeView""" 419 | 420 | def tableOutputFrame(self): 421 | # Treeview Frame Configurations 422 | self.tableFrame = Frame(self.root, bg="#DADDE6") 423 | self.tableFrame.place(x=0, y=400, width=1400, height=560) 424 | self.yScroll = Scrollbar(self.tableFrame) 425 | self.yScroll.pack(side=RIGHT, fill=Y) 426 | 427 | # ttk style object to add configurations 428 | self.style = ttk.Style() 429 | self.style.configure("mystyle.Treeview", font=('Calibri', 12), 430 | rowheight=50) 431 | self.style.configure("mystyle.Treeview.Heading", font=('Times New Roman', 14, "bold"), sticky="w") 432 | 433 | # Formatting the output table view 434 | self.out = ttk.Treeview(self.tableFrame, yscrollcommand=self.yScroll.set, columns=(1, 2, 3, 4, 5, 6, 7), 435 | style="mystyle.Treeview") 436 | self.out.heading("1", text="Session Index") 437 | self.out.column("1", width=5) 438 | self.out.heading("2", text="Student Name") 439 | self.out.heading("3", text="Dance Style") 440 | self.out.column("3", width=20) 441 | self.out.heading("4", text="Session Date") 442 | self.out.column("4", width=5) 443 | self.out.heading("5", text="Booked Day") 444 | self.out.column("5", width=5) 445 | self.out.heading("6", text="Max Rate") 446 | self.out.column("6", width=5) 447 | self.out.heading("7", text="Instructor Name") 448 | self.out.column("7", width=7) 449 | self.out['show'] = 'headings' 450 | 451 | # Virtual Events to trigger methods 452 | self.out.bind("", self.getData) 453 | self.out.bind("<>", self.comboBoxValues) 454 | self.comboInsName.bind("<>", self.displayInsDetails) 455 | 456 | # TreeView output layout configurations 457 | self.out.pack(fill=X) 458 | self.yScroll.config(command=self.out.yview) 459 | --------------------------------------------------------------------------------