- Rewrote frontend from JSX to TypeScript (TSX) - AppLayout with MUI AppBar, ThemeProvider, CssBaseline - HomePage at / with dashboard metrics and recent updates - MetricsPanel with 4 metric cards (total, interviews, offers, rejection rate) - UpdateCard for each job update with status chip - LoadingSkeleton during data fetch - Error Alert on API failure - Create New Job Application button navigating to /applications/new - Vite proxy for /api → backend on :8000 - useDashboardData custom hook with concurrent fetch Closes #2
45 lines
1.3 KiB
Python
45 lines
1.3 KiB
Python
from rest_framework import serializers
|
|
|
|
from .models import JobApplication, JobUpdate
|
|
|
|
|
|
class JobUpdateSerializer(serializers.ModelSerializer):
|
|
company_name = serializers.CharField(source="job_application.company_name", read_only=True)
|
|
position_title = serializers.CharField(source="job_application.position_title", read_only=True)
|
|
job_id = serializers.IntegerField(source="job_application.id", read_only=True)
|
|
|
|
class Meta:
|
|
model = JobUpdate
|
|
fields = [
|
|
"id",
|
|
"job_id",
|
|
"company_name",
|
|
"position_title",
|
|
"from_status",
|
|
"to_status",
|
|
"notes",
|
|
"created_at",
|
|
"metrics",
|
|
]
|
|
|
|
|
|
class JobApplicationSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = JobApplication
|
|
fields = [
|
|
"id",
|
|
"company_name",
|
|
"position_title",
|
|
"status",
|
|
"notes",
|
|
"created_at",
|
|
"updated_at",
|
|
]
|
|
|
|
|
|
class DashboardMetricsSerializer(serializers.Serializer):
|
|
total_applications = serializers.IntegerField()
|
|
status_breakdown = serializers.DictField(child=serializers.IntegerField())
|
|
interviews_count = serializers.IntegerField()
|
|
offers_count = serializers.IntegerField()
|
|
rejection_rate = serializers.FloatField() |