mirror of
https://github.com/EdiFarcas/Giveaway-app.git
synced 2026-06-22 07:00:57 +03:00
Youtube handle try, not working, user input for it.
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `youtubeId` on the `User` table. All the data in the column will be lost.
|
||||
- A unique constraint covering the columns `[youtubeUsername]` on the table `User` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- DropIndex
|
||||
DROP INDEX "User_youtubeId_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" DROP COLUMN "youtubeId",
|
||||
ADD COLUMN "youtubeUsername" TEXT;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_youtubeUsername_key" ON "User"("youtubeUsername");
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[youtubeHandle]` on the table `User` will be added. If there are existing duplicate values, this will fail.
|
||||
- A unique constraint covering the columns `[youtubeChannelId]` on the table `User` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" ADD COLUMN "youtubeChannelId" TEXT,
|
||||
ADD COLUMN "youtubeHandle" TEXT;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_youtubeHandle_key" ON "User"("youtubeHandle");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_youtubeChannelId_key" ON "User"("youtubeChannelId");
|
||||
+12
-10
@@ -8,16 +8,18 @@ generator client {
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
name String?
|
||||
email String? @unique
|
||||
emailVerified DateTime?
|
||||
image String?
|
||||
accounts Account[]
|
||||
sessions Session[]
|
||||
youtubeId String? @unique
|
||||
coins Int @default(0)
|
||||
entries Entry[]
|
||||
id String @id @default(cuid())
|
||||
name String?
|
||||
email String? @unique
|
||||
emailVerified DateTime?
|
||||
image String?
|
||||
accounts Account[]
|
||||
sessions Session[]
|
||||
youtubeUsername String? @unique
|
||||
youtubeHandle String? @unique
|
||||
youtubeChannelId String? @unique
|
||||
coins Int @default(0)
|
||||
entries Entry[]
|
||||
}
|
||||
|
||||
model Account {
|
||||
|
||||
@@ -31,10 +31,39 @@ export const authOptions = {
|
||||
console.error("Sign-in failed: Missing user, account, or profile data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (account.provider === "google" && account.access_token) {
|
||||
try {
|
||||
const { data } = await axios.get("https://www.googleapis.com/youtube/v3/channels", {
|
||||
params: {
|
||||
part: "brandingSettings",
|
||||
mine: "true",
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${account.access_token}`,
|
||||
},
|
||||
});
|
||||
|
||||
const customUrl = data.items?.[0]?.brandingSettings?.channel?.customUrl;
|
||||
|
||||
// Create the handle
|
||||
const youtubeHandle = customUrl ? `@${customUrl.replace(/^.*\//, "")}` : null;
|
||||
|
||||
console.log("Fetched YouTube handle:", youtubeHandle);
|
||||
|
||||
// Attach ONLY the handle to the user
|
||||
user.youtubeHandle = youtubeHandle;
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error fetching YouTube handle:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
async session({ session, user }: { session: any; user: { id: string } }) {
|
||||
session.user.id = user.id; // Attach user ID to the session
|
||||
async session({ session, user }: { session: any; user: any }) {
|
||||
session.user.id = user.id;
|
||||
session.user.youtubeHandle = user.youtubeHandle; // Only attach YouTube handle
|
||||
return session;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { authOptions } from "../auth/[...nextauth]/route";
|
||||
import { db } from "@/lib/db";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const session = await getServerSession(authOptions);
|
||||
|
||||
if (!session?.user?.email) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const { youtubeHandle } = await req.json();
|
||||
|
||||
if (!youtubeHandle || typeof youtubeHandle !== "string") {
|
||||
return NextResponse.json({ error: "Invalid handle" }, { status: 400 });
|
||||
}
|
||||
|
||||
await db.user.update({
|
||||
where: { email: session.user.email },
|
||||
data: { youtubeHandle },
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
"use client"; // <-- add this because we will use onChange, onSubmit!
|
||||
|
||||
import { useState } from "react";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { authOptions } from "../api/auth/[...nextauth]/route";
|
||||
import { db } from "@/lib/db";
|
||||
@@ -13,16 +16,43 @@ export default async function ProfilePage() {
|
||||
const user = await db.user.findUnique({
|
||||
where: { email: session.user?.email! },
|
||||
select: {
|
||||
name: true,
|
||||
email: true,
|
||||
coins: true,
|
||||
},
|
||||
name: true,
|
||||
email: true,
|
||||
coins: true,
|
||||
youtubeHandle: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
redirect("/api/auth/signin");
|
||||
}
|
||||
|
||||
return <ProfileContent user={user} />;
|
||||
}
|
||||
|
||||
// Create a separate component for the UI part
|
||||
function ProfileContent({ user }: { user: any }) {
|
||||
const [youtubeHandle, setYoutubeHandle] = useState(user.youtubeHandle || "");
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
const handleSave = async () => {
|
||||
setSaving(true);
|
||||
try {
|
||||
const res = await fetch("/api/youtube-handle", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ youtubeHandle }),
|
||||
});
|
||||
if (!res.ok) throw new Error("Failed to update");
|
||||
alert("YouTube handle updated successfully!");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert("Error updating handle.");
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
@@ -62,6 +92,27 @@ export default async function ProfilePage() {
|
||||
<p className="font-medium text-gray-500">{user.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* YouTube Handle */}
|
||||
<div className="flex flex-col space-y-2 p-3 bg-gray-50 rounded-lg">
|
||||
<label className="text-sm text-black flex items-center">
|
||||
<span className="text-lg mr-2">📺</span> YouTube Handle
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="p-2 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-purple-600 text-black"
|
||||
placeholder="@yourhandle"
|
||||
value={youtubeHandle}
|
||||
onChange={(e) => setYoutubeHandle(e.target.value)}
|
||||
/>
|
||||
<button
|
||||
onClick={handleSave}
|
||||
disabled={saving}
|
||||
className="bg-purple-600 text-white px-4 py-2 rounded-lg mt-2 hover:bg-purple-700 transition-colors disabled:opacity-50"
|
||||
>
|
||||
{saving ? "Saving..." : "Save Handle"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Coins Section */}
|
||||
@@ -76,7 +127,7 @@ export default async function ProfilePage() {
|
||||
</div>
|
||||
<button className="bg-purple-600 text-white px-4 py-2 rounded-lg hover:bg-purple-700 transition-colors">
|
||||
Add Coins
|
||||
</button> {/* Add functionality to add coins here */}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -102,9 +153,10 @@ export default async function ProfilePage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user