Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .claude/settings.local.json

This file was deleted.

38 changes: 35 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@
def main():
parser = argparse.ArgumentParser(description='StudentHub - Manage your academic life')

parser.add_argument('command', choices=['add-assignment', 'list', 'complete', 'gpa', 'stats','pomodoro'],
help='Command to execute')
parser.add_argument('command', choices=['add-assignment', 'add-grade', 'list', 'complete', 'gpa', 'stats', 'export'],
help='Command to execute')

parser.add_argument('value', nargs='?', help='Value for the command')
parser.add_argument('--deadline', help='Deadline in YYYY-MM-DD format')
parser.add_argument('--subject', help='Subject name')
parser.add_argument('--sessions', type=int, default=4)
parser.add_argument('--work',type=int,default=25)
parser.add_argument('--break-minutes',type=int,default=5)
parser.add_argument('--no-sound',action='store_true')

parser.add_argument('--output', help='Output filename for export')

args = parser.parse_args()

Expand All @@ -40,6 +41,18 @@ def main():
return
assignment = manager.add_assignment(args.value, deadline, args.subject)
print(f"Added assignment: {assignment['title']}")

elif args.command == 'add-grade':
if not args.subject or not args.value:
print("Error: Provide subject name and grade value")
return

try:
grade_value = float(args.value)
manager.add_grade(args.subject, grade_value)
print(f"Grade added for {args.subject}: {grade_value}")
except ValueError:
print("Error: Grade must be a number")

elif args.command == 'list':
assignments = manager.list_assignments()
Expand Down Expand Up @@ -74,6 +87,25 @@ def main():
)
timer.start(interactive=True)

elif args.command == 'export':
if not args.value:
print("Error: choose 'assignments' or 'grades'")
return
if not args.output:
print("Error: specify output with --output filename.csv")
return

if args.value == "assignments":
manager.export_assignments(args.output)
print(f"Assignments exported to {args.output}")

elif args.value == "grades":
manager.export_grades(args.output)
print(f"Grades exported to {args.output}")

else:
print("Invalid export target. Use 'assignments' or 'grades'.")

manager.dump_manager()

if __name__ == '__main__':
Expand Down
28 changes: 26 additions & 2 deletions student_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

from datetime import datetime
from utils import calculate_days_remaining, validate_grade, get_priority_level, save_to_json, load_from_json
from utils import calculate_days_remaining, validate_grade, get_priority_level, save_to_json, load_from_json, export_to_csv


class StudentManager:
Expand Down Expand Up @@ -111,6 +111,30 @@ def get_statistics(self):
'pending': total_assignments - completed,
'gpa': self.calculate_gpa()
}

def export_assignments(self, filename):
"""Export assignments to CSV"""
cleaned = []
for a in self.assignments:
cleaned.append({
"title": a["title"],
"deadline": a["deadline"].strftime("%Y-%m-%d"),
"subject": a["subject"],
"completed": a["completed"],
"created_at": a["created_at"].strftime("%Y-%m-%d")
})
export_to_csv(cleaned, filename)

def export_grades(self, filename):
"""Export grades to CSV"""
cleaned = []
for g in self.grades:
cleaned.append({
"subject": g["subject"],
"grade": g["grade"],
"date": g["date"].strftime("%Y-%m-%d")
})
export_to_csv(cleaned, filename)

def _ser_object(self):
"""
Expand All @@ -135,4 +159,4 @@ def _deser_object(cls, data):
manager = cls()
manager.assignments = data.get("Assignments", [])
manager.grades = data.get("Grades", [])
return manager
return manager
16 changes: 15 additions & 1 deletion utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from datetime import datetime
import json
import csv
import os

class DateTimeEncoder(json.JSONEncoder):
Expand Down Expand Up @@ -95,4 +96,17 @@ def get_priority_level(days_remaining):
elif days_remaining <= 7:
return "MEDIUM"
else:
return "LOW"
return "LOW"

def export_to_csv(data, filename, headers=None):
"""Export list of dicts to CSV"""
if not data:
raise ValueError("No data to export")

if headers is None:
headers = list(data[0].keys())

with open(filename, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=headers)
writer.writeheader()
writer.writerows(data)