- {userIsLogged ? (
+ {userIsLogged || placeholderDataSelected ? (
) : (
diff --git a/src/app/utils/getSpotifyData.ts b/src/app/utils/getSpotifyData.ts
new file mode 100644
index 0000000..2511e86
--- /dev/null
+++ b/src/app/utils/getSpotifyData.ts
@@ -0,0 +1,62 @@
+import SpotifyWebApi from "spotify-web-api-node";
+import { FETCH_ARTISTS_LIMIT, FETCH_TRACKS_LIMIT } from "./contants";
+import { TrackByAlbum } from "../_components/spotify-data";
+
+export const getSpotifyData = async ({
+ accessToken,
+}: {
+ accessToken: string;
+}) => {
+ const spotifyApi = new SpotifyWebApi({
+ clientId: process.env.SPOTIFY_CLIENT_ID,
+ clientSecret: process.env.SPOTIFY_CLIENT_SECRET,
+ redirectUri: process.env.SPOTIFY_REDIRECT_URI,
+ });
+ spotifyApi.setAccessToken(accessToken);
+
+ const [artistsData, tracksData, userData] = await Promise.all([
+ spotifyApi.getMyTopArtists({
+ limit: FETCH_ARTISTS_LIMIT,
+ time_range: "short_term",
+ }),
+ spotifyApi.getMyTopTracks({
+ limit: FETCH_TRACKS_LIMIT,
+ time_range: "short_term",
+ }),
+ spotifyApi.getMe(),
+ ]);
+
+ const artists = artistsData.body.items;
+ const tracks = tracksData.body.items.map((track, i) => ({
+ ...track,
+ position: i + 1,
+ }));
+
+ const tracksByAlbum = tracksData.body.items.reduce(
+ (acc: Record, track) => {
+ if (!acc[track.album.id]) {
+ const tracksWithAlbum = tracks.filter(
+ (t) => t.album.id === track.album.id,
+ );
+ acc[track.album.id] = {
+ album: track.album,
+ position:
+ tracksWithAlbum.reduce(
+ (acc, _track) => FETCH_TRACKS_LIMIT / _track.position + acc,
+ 0,
+ ) / tracksWithAlbum.length,
+ tracks: [],
+ };
+ }
+ (acc[track.album.id] || ({ tracks: [] } as any)).tracks.push(track);
+ return acc;
+ },
+ {},
+ );
+
+ return {
+ userData,
+ tracksByAlbum,
+ artists,
+ };
+};
diff --git a/src/server/api/root.ts b/src/server/api/root.ts
index 64cf98f..ba66e95 100644
--- a/src/server/api/root.ts
+++ b/src/server/api/root.ts
@@ -2,6 +2,7 @@ import { postRouter } from "@/server/api/routers/post";
import { createCallerFactory, createTRPCRouter } from "@/server/api/trpc";
import * as cloudinary from "cloudinary";
import { entryRouter } from "./routers/entry";
+import { userDataRouter } from "./routers/user-data";
cloudinary.v2.config({
secure: true,
@@ -15,6 +16,7 @@ cloudinary.v2.config({
export const appRouter = createTRPCRouter({
post: postRouter,
entry: entryRouter,
+ userData: userDataRouter,
});
// export type definition of API
diff --git a/src/server/api/routers/user-data.ts b/src/server/api/routers/user-data.ts
new file mode 100644
index 0000000..5cb0143
--- /dev/null
+++ b/src/server/api/routers/user-data.ts
@@ -0,0 +1,160 @@
+import { z } from "zod";
+import { createTRPCRouter, publicProcedure } from "../trpc";
+
+export const userDataRouter = createTRPCRouter({
+ get: publicProcedure
+ .input(z.object({ spotifyUserId: z.string() }))
+ .query(async ({ ctx, input }) => {
+ const spotifyUser = await ctx.db.spotifyUser.findUnique({
+ where: {
+ spotifyUserId: input.spotifyUserId,
+ },
+ });
+ if (!spotifyUser) {
+ return null;
+ }
+ const userData = await ctx.db.userData.findFirst({
+ include: {
+ spotifyUser: {
+ select: {
+ spotifyUserId: true,
+ displayName: true,
+ images: true,
+ },
+ },
+ artists: {
+ select: {
+ name: true,
+ images: true,
+ },
+ },
+ // albums: {
+ // select: {
+ // name: true,
+ // images: true,
+ // tracks: {
+ // select: {
+ // name: true,
+ // },
+ // },
+ // },
+ // },
+ },
+ where: {
+ spotifyUser: {
+ spotifyUserId: input.spotifyUserId,
+ },
+ },
+ });
+
+ if (!userData) {
+ return null;
+ }
+
+ return {
+ ...userData,
+ spotifyUser: {
+ ...spotifyUser,
+ images: userData.spotifyUser.images,
+ id: spotifyUser.spotifyUserId,
+ },
+ tracksByAlbum: JSON.parse(userData.tracksByAlbum),
+ };
+ }),
+ create: publicProcedure
+ .input(
+ z.object({
+ spotifyUserId: z.string(),
+ tracksByAlbum: z.record(
+ z.object({
+ album: z.object({
+ id: z.string(),
+ name: z.string(),
+ images: z.array(
+ z.object({
+ url: z.string(),
+ }),
+ ),
+ }),
+ position: z.number(),
+ tracks: z.array(
+ z.object({
+ id: z.string(),
+ name: z.string(),
+ }),
+ ),
+ }),
+ ),
+ artists: z.array(
+ z.object({
+ name: z.string(),
+ images: z.array(
+ z.object({
+ url: z.string(),
+ }),
+ ),
+ }),
+ ),
+ user: z.object({
+ id: z.string(),
+ displayName: z.string(),
+ images: z.array(
+ z.object({
+ url: z.string(),
+ }),
+ ),
+ }),
+ }),
+ )
+ .mutation(async ({ ctx, input }) => {
+ const spotifyUser = await ctx.db.spotifyUser.findUnique({
+ where: {
+ spotifyUserId: input.spotifyUserId,
+ },
+ });
+ if (spotifyUser) {
+ return null;
+ }
+ await ctx.db.userData.create({
+ data: {
+ spotifyUser: {
+ create: {
+ displayName: input.user.displayName,
+ spotifyUserId: input.user.id,
+ images: {
+ create: input.user.images.map((image) => ({
+ url: image.url,
+ })),
+ },
+ },
+ },
+ artists: {
+ create: input.artists.map((artist) => ({
+ name: artist.name,
+ images: {
+ create: artist.images.map((image) => ({
+ url: image.url,
+ })),
+ },
+ })),
+ },
+ // albums: {
+ // create: input.albums.map((album) => ({
+ // name: album.name,
+ // images: {
+ // create: album.images.map((image) => ({
+ // url: image.url,
+ // })),
+ // },
+ // tracks: {
+ // create: album.tracks.map((track) => ({
+ // name: track.name,
+ // })),
+ // },
+ // })),
+ // },
+ tracksByAlbum: JSON.stringify(input.tracksByAlbum),
+ },
+ });
+ }),
+});