nu met de juiste files toegevoegd

This commit is contained in:
2025-08-03 10:50:49 +02:00
parent 54883d34c0
commit c21c98f6c4
6 changed files with 35 additions and 52 deletions
+1 -11
View File
@@ -2,16 +2,6 @@ from django.contrib.auth.models import User
from rest_framework import serializers from rest_framework import serializers
class UserSerializer(serializers.HyperlinkedModelSerializer): class UserSerializer(serializers.HyperlinkedModelSerializer):
# Add explicit reverse lookup to profile
profile = serializers.HyperlinkedRelatedField(
view_name='api-profile',
lookup_field='id',
read_only=True
)
class Meta: class Meta:
model = User model = User
fields = ['url', 'id', 'username', 'email', 'profile'] fields = ['id', 'username', 'email']
extra_kwargs = {
'url': {'view_name': 'api-user', 'lookup_field': 'id'}
}
+1 -5
View File
@@ -19,11 +19,7 @@ urlpatterns = [
path('api/vote/', views.VoteListView.as_view(), name="api-votes"), path('api/vote/', views.VoteListView.as_view(), name="api-votes"),
path('api/vote/<id>', views.VoteDetailView.as_view(), name="api-vote"), path('api/vote/<id>', views.VoteDetailView.as_view(), name="api-vote"),
path('api/user/', views.UserListView.as_view(), name="api-users"), path('api/user/', views.UserListView.as_view(), name="api-users"),
path('api/user/<int:id>', views.UserDetailView.as_view(), name="api-user"), path('api/profile/me', views.ProfileMeView.as_view(), name="api-profile-me"),
path('api/user/<int:user_id>/votes', views.VoteListView.as_view(), name="api-user-votes"),
path('api/profile/<int:id>', views.ProfileDetailView.as_view(), name="api-profile"),
path('api/profile/background', views.BackgroundListView.as_view(), name="api-backgrounds"),
path('api/profile/background/<int:id>', views.BackgroundDetailView.as_view(), name="api-background"),
### Classic ### Classic
path('track/', views.NominateView.as_view(), name="nominate"), path('track/', views.NominateView.as_view(), name="nominate"),
+3 -23
View File
@@ -5,28 +5,8 @@ from rest_framework.response import Response
from playlist.serializers import ProfileSerializer, ProfileUpdateSerializer, BackgroundSerializer from playlist.serializers import ProfileSerializer, ProfileUpdateSerializer, BackgroundSerializer
from playlist.models import Profile, Background from playlist.models import Profile, Background
class ProfileDetailView(APIView): class ProfileMeView(APIView):
def get(self, request, id): def get(self, request):
profile = Profile.objects.get(pk=id) profile = request.user.profile
serializer = ProfileSerializer(profile) serializer = ProfileSerializer(profile)
return Response(serializer.data) return Response(serializer.data)
def put(self, request, id):
profile = Profile.objects.get(pk=id)
serializer = ProfileUpdateSerializer(profile, data=request.data)
serializer.is_valid()
serializer.save()
return Response(serializer.data)
#return Response()
class BackgroundListView(APIView):
def get(self, request):
backgrounds = Background.objects.all()
serializer = BackgroundSerializer(backgrounds, many=True)
return Response(serializer.data)
class BackgroundDetailView(APIView):
def get(self, request, id):
background = Background.objects.get(pk=id)
serializer = BackgroundSerializer(background)
return Response(serializer.data)
+11 -1
View File
@@ -1,3 +1,4 @@
from json.decoder import JSONDecodeError
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.response import Response
from playlist.models import Track, Profile from playlist.models import Track, Profile
@@ -74,7 +75,16 @@ class TrackVoteView(APIView):
) )
def get(self, request): def get(self, request):
# TODO implement a session-based vote tracking system. Random return for now. # TODO implement a session-based vote tracking system. Random return for now.
random_pk = choice(Track.objects.values_list('pk', flat=True)) track_pks = Track.objects.values_list('pk', flat=True)
if not track_pks:
dummy = {
"name": "Dummy",
"artist": "Dummy",
"album_cover": "/meowl.png"
}
return Response(dummy)
random_pk = choice(track_pks)
track = Track.objects.get(pk=random_pk) track = Track.objects.get(pk=random_pk)
serializer = TrackSerializer(track, context={'request': request}) serializer = TrackSerializer(track, context={'request': request})
return Response(serializer.data) return Response(serializer.data)
+17 -2
View File
@@ -6,6 +6,7 @@ import { oidcConfig, userManager } from "muzak/config/auth";
import { Source_Sans_3, Nunito } from "next/font/google"; import { Source_Sans_3, Nunito } from "next/font/google";
import AuthStatus from "muzak/components/AuthStatus"; import AuthStatus from "muzak/components/AuthStatus";
import NavigationBar from "muzak/components/NavigationBar"; import NavigationBar from "muzak/components/NavigationBar";
import Quota from "muzak/components/Quota";
const sourceSans = Source_Sans_3({ const sourceSans = Source_Sans_3({
weight: ["400"], weight: ["400"],
@@ -16,12 +17,21 @@ const nunito = Nunito({
subsets: ["latin"], subsets: ["latin"],
}); });
function LayoutContent({ children }: { children: React.ReactNode }) { function LayoutContent({
children,
quota,
setQuota,
}: {
children: React.ReactNode;
quota: number | null;
setQuota: React.Dispatch<React.SetStateAction<number | null>>;
}) {
return ( return (
<> <>
<AuthStatus /> <AuthStatus />
{children} {children}
<NavigationBar /> <NavigationBar />
<Quota quota={quota} setQuota={setQuota} />
</> </>
); );
} }
@@ -32,6 +42,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const [isAnimate, setIsAnimate] = useState(false); const [isAnimate, setIsAnimate] = useState(false);
const [quota, setQuota] = useState<number | null>(null);
const toggleAnimation = () => { const toggleAnimation = () => {
setIsAnimate(!isAnimate); setIsAnimate(!isAnimate);
@@ -41,7 +52,11 @@ export default function RootLayout({
<html lang="en" className={nunito.className}> <html lang="en" className={nunito.className}>
<body className={`bg-game-show ${isAnimate ? "animate" : ""} h-screen`}> <body className={`bg-game-show ${isAnimate ? "animate" : ""} h-screen`}>
<AuthProvider {...oidcConfig}> <AuthProvider {...oidcConfig}>
<LayoutContent>{children}</LayoutContent> <LayoutContent
children={children}
quota={quota}
setQuota={setQuota}
/>
</AuthProvider> </AuthProvider>
<button <button
className={`absolute top-1 left-1 ${isAnimate ? "pause" : "play"}`} className={`absolute top-1 left-1 ${isAnimate ? "pause" : "play"}`}
+2 -10
View File
@@ -64,21 +64,12 @@ export const api = {
votes: { votes: {
list: fetcher.path("/api/vote/").method("get").create(), list: fetcher.path("/api/vote/").method("get").create(),
detail: fetcher.path("/api/vote/{id}").method("get").create(), detail: fetcher.path("/api/vote/{id}").method("get").create(),
userVotes: fetcher.path("/api/user/{user_id}/votes").method("get").create(),
}, },
users: { users: {
list: fetcher.path("/api/user/").method("get").create(), list: fetcher.path("/api/user/").method("get").create(),
detail: fetcher.path("/api/user/{id}").method("get").create(),
}, },
profiles: { profiles: {
detail: fetcher.path("/api/profile/{id}").method("get").create(), me: fetcher.path("/api/profile/me").method("get").create(),
backgrounds: {
list: fetcher.path("/api/profile/background").method("get").create(),
detail: fetcher
.path("/api/profile/background/{id}")
.method("get")
.create(),
},
}, },
}; };
@@ -86,5 +77,6 @@ export type User = components["schemas"]["User"];
export type Track = components["schemas"]["Track"]; export type Track = components["schemas"]["Track"];
export type Album = components["schemas"]["Album"]; export type Album = components["schemas"]["Album"];
export type Vote = components["schemas"]["Vote"]; export type Vote = components["schemas"]["Vote"];
export type Profile = components["schemas"]["Profile"];
export default api; export default api;