Added impersonation for admins
This commit is contained in:
91
app/api/account/impersonate/route.ts
Normal file
91
app/api/account/impersonate/route.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUser from "@/lib/fetch-user";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUser(req)
|
||||
if (!user || user.role != "ADMIN") {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const impersonation = await db.impersonation.findFirst({
|
||||
where: {
|
||||
sourceId: user.id
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(impersonation);
|
||||
} catch (error) {
|
||||
console.log("[AUTH/ACCOUNT/IMPERSONATION]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUser(req)
|
||||
if (!user || user.role != "ADMIN") {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { targetId } = await req.json();
|
||||
|
||||
const impersonation = await db.impersonation.create({
|
||||
data: {
|
||||
sourceId: user.id,
|
||||
targetId
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(impersonation);
|
||||
} catch (error) {
|
||||
console.log("[AUTH/ACCOUNT/IMPERSONATION]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(req: Request) {
|
||||
try {
|
||||
const user = await fetchUser(req)
|
||||
if (!user || user.role != "ADMIN") {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { targetId } = await req.json();
|
||||
|
||||
const impersonation = await db.impersonation.update({
|
||||
where: {
|
||||
sourceId: user.id,
|
||||
},
|
||||
data: {
|
||||
targetId
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(impersonation);
|
||||
} catch (error) {
|
||||
console.log("[AUTH/ACCOUNT/IMPERSONATION]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const user = await fetchUser(req)
|
||||
if (!user || user.role != "ADMIN") {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const impersonation = await db.impersonation.delete({
|
||||
where: {
|
||||
sourceId: user.id
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json(impersonation)
|
||||
} catch (error) {
|
||||
console.log("[AUTH/ACCOUNT/IMPERSONATION]", error);
|
||||
return new NextResponse("Internal Error" + error, { status: 500 });
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import { auth } from "@/auth";
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUser from "@/lib/fetch-user";
|
||||
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
return NextResponse.json(await fetchUserUsingAPI(req))
|
||||
return NextResponse.json(await fetchUser(req))
|
||||
} catch (error) {
|
||||
console.log("[ACCOUNT]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { db } from "@/lib/db"
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import voices from "@/data/tts";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
@ -26,7 +26,7 @@ export async function GET(req: Request) {
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
@ -24,7 +24,7 @@ export async function GET(req: Request) {
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
@ -57,7 +57,7 @@ export async function POST(req: Request) {
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
@ -24,7 +24,7 @@ export async function GET(req: Request) {
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
@ -35,7 +35,7 @@ export async function POST(req: Request) {
|
||||
data: {
|
||||
search,
|
||||
replace,
|
||||
userId: user.id as string
|
||||
userId: user.id
|
||||
}
|
||||
});
|
||||
|
||||
@ -48,7 +48,7 @@ export async function POST(req: Request) {
|
||||
|
||||
export async function PUT(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
@ -61,7 +61,8 @@ export async function PUT(req: Request) {
|
||||
},
|
||||
data: {
|
||||
search,
|
||||
replace
|
||||
replace,
|
||||
userId: user.id
|
||||
}
|
||||
});
|
||||
|
||||
@ -74,7 +75,7 @@ export async function PUT(req: Request) {
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
@ -87,7 +88,7 @@ export async function DELETE(req: Request) {
|
||||
const filter = await db.ttsWordFilter.delete({
|
||||
where: {
|
||||
userId_search: {
|
||||
userId: user.id as string,
|
||||
userId: user.id,
|
||||
search
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import voices from "@/data/tts";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
@ -40,7 +40,7 @@ export async function GET(req: Request) {
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
@ -1,12 +1,17 @@
|
||||
import { db } from "@/lib/db"
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET(req: Request, { params } : { params: { id: string } }) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
let id = req.headers?.get('x-api-key')
|
||||
if (id == null) {
|
||||
return NextResponse.json(null);
|
||||
return NextResponse.json(null);
|
||||
}
|
||||
|
||||
const tokens = await db.apiKey.findFirst({
|
||||
@ -18,15 +23,19 @@ export async function GET(req: Request, { params } : { params: { id: string } })
|
||||
return NextResponse.json(tokens);
|
||||
} catch (error) {
|
||||
console.log("[TOKEN/GET]", error);
|
||||
return new NextResponse("Internal Error", { status: 500});
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(req: Request, { params } : { params: { id: string } }) {
|
||||
try {
|
||||
const { id } = params
|
||||
const user = await fetchUserUsingAPI(req)
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { id } = params
|
||||
const token = await db.apiKey.delete({
|
||||
where: {
|
||||
id,
|
||||
@ -37,6 +46,6 @@ export async function DELETE(req: Request, { params } : { params: { id: string }
|
||||
return NextResponse.json(token);
|
||||
} catch (error) {
|
||||
console.log("[TOKEN/DELETE]", error);
|
||||
return new NextResponse("Internal Error", { status: 500});
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import { db } from "@/lib/db"
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserUsingAPI(req);
|
||||
const user = await fetchUserWithImpersonation(req);
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
@ -1,13 +1,18 @@
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUserWithImpersonation from "@/lib/fetch-user-impersonation";
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
let { userId, label } = await req.json();
|
||||
|
||||
if (userId == null) {
|
||||
const user = await fetchUserUsingAPI(req);
|
||||
const user = await fetchUserWithImpersonation(req);
|
||||
if (user != null) {
|
||||
userId = user.id;
|
||||
}
|
||||
@ -31,9 +36,13 @@ export async function POST(req: Request) {
|
||||
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const user = await fetchUserWithImpersonation(req)
|
||||
if (!user) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
let { id } = await req.json();
|
||||
const user = await fetchUserUsingAPI(req);
|
||||
if (!id || !user) {
|
||||
if (!id) {
|
||||
return NextResponse.json(null)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import fetchUserUsingAPI from "@/lib/validate-api";
|
||||
import fetchUser from "@/lib/fetch-user";
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
@ -8,7 +8,7 @@ export async function GET(req: Request) {
|
||||
let userId = searchParams.get('userId')
|
||||
|
||||
if (userId == null) {
|
||||
const user = await fetchUserUsingAPI(req);
|
||||
const user = await fetchUser(req);
|
||||
if (user != null) {
|
||||
userId = user.id as string;
|
||||
}
|
||||
|
41
app/api/users/route.ts
Normal file
41
app/api/users/route.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { db } from "@/lib/db"
|
||||
import { NextResponse } from "next/server";
|
||||
import fetchUser from "@/lib/fetch-user";
|
||||
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const user = await fetchUser(req)
|
||||
if (!user || user.role != "ADMIN") {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(req.url)
|
||||
const qn = searchParams.get('qn') as string
|
||||
const id = searchParams.get('id') as string
|
||||
|
||||
if (qn) {
|
||||
const users = await db.user.findMany({
|
||||
where: {
|
||||
name: {
|
||||
contains: qn
|
||||
}
|
||||
}
|
||||
})
|
||||
return NextResponse.json(users)
|
||||
}
|
||||
if (id) {
|
||||
const users = await db.user.findUnique({
|
||||
where: {
|
||||
id: id
|
||||
}
|
||||
})
|
||||
return NextResponse.json(users)
|
||||
}
|
||||
|
||||
const users = await db.user.findMany();
|
||||
return NextResponse.json(users)
|
||||
} catch (error) {
|
||||
console.log("[AUTH/ACCOUNT/IMPERSONATION]", error);
|
||||
return new NextResponse("Internal Error", { status: 500 });
|
||||
}
|
||||
}
|
@ -20,7 +20,6 @@ const SettingsPage = () => {
|
||||
try {
|
||||
const keys = (await axios.get("/api/tokens")).data ?? {};
|
||||
setApiKeys(keys)
|
||||
console.log(keys);
|
||||
} catch (error) {
|
||||
console.log("ERROR", error)
|
||||
}
|
||||
@ -49,20 +48,6 @@ const SettingsPage = () => {
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const keys = (await axios.get("/api/tokens")).data;
|
||||
setApiKeys(keys)
|
||||
console.log(keys);
|
||||
} catch (error) {
|
||||
console.log("ERROR", error)
|
||||
}
|
||||
};
|
||||
|
||||
fetchData().catch(console.error);
|
||||
}, [apiKeyViewable]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="px-10 py-5 mx-5 my-10">
|
||||
|
@ -13,8 +13,7 @@ import { useForm } from "react-hook-form";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
|
||||
import * as z from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { DropdownMenu, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { DropdownMenuContent, DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { Label } from "@/components/ui/label";
|
||||
|
||||
|
||||
@ -58,7 +57,6 @@ const TTSFiltersPage = () => {
|
||||
|
||||
try {
|
||||
const replacementData = await axios.get("/api/settings/tts/filter/words")
|
||||
console.log(replacementData.data)
|
||||
setReplacements(replacementData.data ?? [])
|
||||
} catch (e) {
|
||||
console.log("ERROR", e)
|
||||
@ -112,8 +110,9 @@ const TTSFiltersPage = () => {
|
||||
const onReplaceAdd = async () => {
|
||||
await axios.post("/api/settings/tts/filter/words", { search, replace })
|
||||
.then(d => {
|
||||
replacements.push(d.data)
|
||||
replacements.push({ id: d.data.id, search: d.data.search, replace: d.data.replace, userId: d.data.userId })
|
||||
setReplacements(replacements)
|
||||
setSearch("")
|
||||
}).catch(e => {
|
||||
// TODO: handle already exist.
|
||||
console.log("LOGGED:", e)
|
||||
@ -135,7 +134,9 @@ const TTSFiltersPage = () => {
|
||||
const onReplaceDelete = async (id: string) => {
|
||||
await axios.delete("/api/settings/tts/filter/words?id=" + id)
|
||||
.then(d => {
|
||||
setReplacements(replacements.filter(r => r.id != id))
|
||||
const r = replacements.filter(r => r.id != d.data.id)
|
||||
setReplacements(r)
|
||||
console.log(r)
|
||||
}).catch(e => {
|
||||
// TODO: handle does not exist.
|
||||
console.log("LOGGED:", e)
|
||||
@ -166,9 +167,9 @@ const TTSFiltersPage = () => {
|
||||
<div>
|
||||
<div className="text-2xl text-center pt-[50px]">TTS Filters</div>
|
||||
<div className="px-10 py-5 w-full h-full flex-grow inset-y-1/2">
|
||||
<div className="">
|
||||
<div>
|
||||
{userTags.map((user, index) => (
|
||||
<div className="flex w-full items-start justify-between rounded-md border px-4 py-1">
|
||||
<div key={user.username + "-tags"} className="flex w-full items-start justify-between rounded-md border px-4 py-1">
|
||||
<p className="text-base font-medium">
|
||||
<span className="mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-primary-foreground">
|
||||
{user.tag}
|
||||
@ -200,7 +201,7 @@ const TTSFiltersPage = () => {
|
||||
<CommandGroup>
|
||||
{tags.map((tag) => (
|
||||
<CommandItem
|
||||
key={tag}
|
||||
key={user.username + "-tag"}
|
||||
value={tag}
|
||||
onSelect={(value) => {
|
||||
onAddExtended({ username: userTags[index].username, tag: value}, false)
|
||||
@ -216,7 +217,7 @@ const TTSFiltersPage = () => {
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuSub>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={onDelete} className="text-red-600">
|
||||
<DropdownMenuItem key={user.username + "-delete"} onClick={onDelete} className="text-red-600">
|
||||
<Trash className="mr-2 h-4 w-4" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
@ -235,7 +236,7 @@ const TTSFiltersPage = () => {
|
||||
control={usernameFilteredForm.control}
|
||||
name="username"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-grow">
|
||||
<FormItem key={"new-username"} className="flex-grow">
|
||||
<FormControl>
|
||||
<Input id="username" placeholder="Enter a twitch username" {...field} />
|
||||
</FormControl>
|
||||
@ -272,6 +273,7 @@ const TTSFiltersPage = () => {
|
||||
{tags.map((tag) => (
|
||||
<CommandItem
|
||||
value={tag}
|
||||
key={tag + "-tag"}
|
||||
onSelect={(value) => {
|
||||
setTag(value)
|
||||
setOpen(false)
|
||||
@ -297,7 +299,7 @@ const TTSFiltersPage = () => {
|
||||
<p className="text-center text-2xl text-white pt-[80px]">Regex Replacement</p>
|
||||
<div>
|
||||
{replacements.map((term: { id: string, search: string, replace: string, userId: string }) => (
|
||||
<div className="flex flex-row w-full items-start justify-between rounded-lg border px-4 py-3 gap-3 mt-[15px]">
|
||||
<div key={term.id} className="flex flex-row w-full items-start justify-between rounded-lg border px-4 py-3 gap-3 mt-[15px]">
|
||||
<Input id="search" placeholder={term.search} className="flex" onChange={e => term.search = e.target.value } defaultValue={term.search} />
|
||||
<Input id="replace" placeholder={term.replace} className="flex" onChange={e => term.replace = e.target.value } defaultValue={term.replace} />
|
||||
<Button className="bg-blue-500 hover:bg-blue-600 items-center align-middle" onClick={_ => onReplaceUpdate(term)}>
|
||||
|
@ -14,7 +14,7 @@ import { Label } from "@/components/ui/label";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import voices from "@/data/tts";
|
||||
|
||||
const TTSFiltersPage = () => {
|
||||
const TTSVoiceFiltersPage = () => {
|
||||
const { data: session, status } = useSession();
|
||||
const [loading, setLoading] = useState<boolean>(true)
|
||||
|
||||
@ -88,7 +88,7 @@ const TTSFiltersPage = () => {
|
||||
<CommandGroup>
|
||||
{voices.map((voice) => (
|
||||
<CommandItem
|
||||
key={voice.value}
|
||||
key={voice.value + "-" + voice.label}
|
||||
value={voice.value}
|
||||
onSelect={(currentValue) => {
|
||||
setValue(Number.parseInt(currentValue))
|
||||
@ -115,7 +115,7 @@ const TTSFiltersPage = () => {
|
||||
<p className="text-xl text-center justify-center">Voices Enabled</p>
|
||||
<div className="grid grid-cols-4 grid-flow-row gap-4 pt-[20px]">
|
||||
{voices.map((v, i) => (
|
||||
<div className="h-[30px] row-span-1 col-span-1 align-middle flex items-center justify-center">
|
||||
<div key={v.label + "-enabled"} className="h-[30px] row-span-1 col-span-1 align-middle flex items-center justify-center">
|
||||
<Checkbox onClick={() => {
|
||||
const newVal = enabled ^ (1 << (Number.parseInt(v.value) - 1))
|
||||
setEnabled(newVal)
|
||||
@ -132,4 +132,4 @@ const TTSFiltersPage = () => {
|
||||
);
|
||||
}
|
||||
|
||||
export default TTSFiltersPage;
|
||||
export default TTSVoiceFiltersPage;
|
Reference in New Issue
Block a user