├── .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 |
4 |
5 |
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 |
4 |
5 |
10 |
11 |
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 | 
10 |
11 | Admin Control Panel to Manage Instructors and Sessions.
12 | 
13 |
14 | CRUD operations allowed to the Admin.
15 | 
16 |
17 | Instructor Control Panel
18 | 
19 |
20 | Sessions Panel - to match the instructors with the students. (Admin View)
21 | 
22 |
23 | Sessions Panel - Assigning Instructors
24 | 
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 |
--------------------------------------------------------------------------------