Skip to content

Commit 2b64efa

Browse files
Enhance registration page UI and implement API for answer creation and deletion
1 parent 894da40 commit 2b64efa

File tree

2 files changed

+170
-10
lines changed

2 files changed

+170
-10
lines changed

src/(auth)/register/page.tsx

Lines changed: 104 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
11
"use client";
22
import { useAuthStore } from '@/store/Auth'
33
import React from 'react'
4+
import { Label } from "@/components/ui/label";
5+
import { Input } from "@/components/ui/input";
6+
import { cn } from "@/lib/utils";
7+
import { IconBrandGithub, IconBrandGoogle } from "@tabler/icons-react";
8+
import Link from 'next/link';
9+
10+
11+
const BottomGradient = () => {
12+
return (
13+
<>
14+
<span className="absolute inset-x-0 -bottom-px block h-px w-full bg-gradient-to-r from-transparent via-cyan-500 to-transparent opacity-0 transition duration-500 group-hover/btn:opacity-100" />
15+
<span className="absolute inset-x-10 -bottom-px mx-auto block h-px w-1/2 bg-gradient-to-r from-transparent via-indigo-500 to-transparent opacity-0 blur-sm transition duration-500 group-hover/btn:opacity-100" />
16+
</>
17+
);
18+
};
19+
20+
const LabelInputContainer = ({
21+
children,
22+
className,
23+
}: {
24+
children: React.ReactNode;
25+
className?: string;
26+
}) => {
27+
return <div className={cn("flex w-full flex-col space-y-2", className)}>{children}</div>;
28+
};
429

530
export default function Registerpage() {
631
const {createAccount, login} = useAuthStore();
@@ -39,15 +64,84 @@ export default function Registerpage() {
3964
setIsLoading(false);
4065
}
4166
return (
42-
<div>
43-
{error && (
44-
<p>{error}</p>
45-
)}
46-
<form onSubmit={handleSubmit}>
47-
<button>
48-
{isLoading ? 'Loading' : 'Submit'}
49-
</button>
50-
</form>
51-
</div>
67+
<div className="mx-auto w-full max-w-md rounded-none border border-solid border-white/30 bg-white p-4 shadow-input dark:bg-black md:rounded-2xl md:p-8">
68+
<h2 className="text-xl font-bold text-neutral-800 dark:text-neutral-200">
69+
Welcome to Riverflow
70+
</h2>
71+
<p className="mt-2 max-w-sm text-sm text-neutral-600 dark:text-neutral-300">
72+
Signup with riverflow if you you don&apos;t have an account.
73+
<br /> If you already have an account,{" "}
74+
<Link href="/login" className="text-orange-500 hover:underline">
75+
login
76+
</Link>{" "}
77+
to riverflow
78+
</p>
79+
80+
{error && (
81+
<p className="mt-8 text-center text-sm text-red-500 dark:text-red-400">{error}</p>
82+
)}
83+
<form className="my-8" onSubmit={handleSubmit}>
84+
<div className="mb-4 flex flex-col space-y-2 md:flex-row md:space-x-2 md:space-y-0">
85+
<LabelInputContainer>
86+
<Label htmlFor="firstname">First name</Label>
87+
<Input className="text-black" id="firstname" name="firstname" placeholder="Tyler" type="text" />
88+
</LabelInputContainer>
89+
<LabelInputContainer>
90+
<Label htmlFor="lastname">Last name</Label>
91+
<Input className="text-black" id="lastname" name="lastname" placeholder="Durden" type="text" />
92+
</LabelInputContainer>
93+
</div>
94+
<LabelInputContainer className="mb-4">
95+
<Label htmlFor="email">Email Address</Label>
96+
<Input
97+
className="text-black"
98+
id="email"
99+
name="email"
100+
placeholder="projectmayhem@fc.com"
101+
type="email"
102+
/>
103+
</LabelInputContainer>
104+
<LabelInputContainer className="mb-4">
105+
<Label htmlFor="password">Password</Label>
106+
<Input className="text-black" id="password" name="password" placeholder="••••••••" type="password" />
107+
</LabelInputContainer>
108+
109+
<button
110+
className="group/btn relative block h-10 w-full rounded-md bg-gradient-to-br from-black to-neutral-600 font-medium text-white shadow-[0px_1px_0px_0px_#ffffff40_inset,0px_-1px_0px_0px_#ffffff40_inset] dark:bg-zinc-800 dark:from-zinc-900 dark:to-zinc-900 dark:shadow-[0px_1px_0px_0px_var(--zinc-800)_inset,0px_-1px_0px_0px_var(--zinc-800)_inset]"
111+
type="submit"
112+
disabled={isLoading}
113+
>
114+
Sign up &rarr;
115+
<BottomGradient />
116+
</button>
117+
118+
<div className="my-8 h-[1px] w-full bg-gradient-to-r from-transparent via-neutral-300 to-transparent dark:via-neutral-700" />
119+
120+
<div className="flex flex-col space-y-4">
121+
<button
122+
className="group/btn relative flex h-10 w-full items-center justify-start space-x-2 rounded-md bg-gray-50 px-4 font-medium text-black shadow-input dark:bg-zinc-900 dark:shadow-[0px_0px_1px_1px_var(--neutral-800)]"
123+
type="button"
124+
disabled={isLoading}
125+
>
126+
<IconBrandGoogle className="h-4 w-4 text-neutral-800 dark:text-neutral-300" />
127+
<span className="text-sm text-neutral-700 dark:text-neutral-300">
128+
Google
129+
</span>
130+
<BottomGradient />
131+
</button>
132+
<button
133+
className="group/btn relative flex h-10 w-full items-center justify-start space-x-2 rounded-md bg-gray-50 px-4 font-medium text-black shadow-input dark:bg-zinc-900 dark:shadow-[0px_0px_1px_1px_var(--neutral-800)]"
134+
type="button"
135+
disabled={isLoading}
136+
>
137+
<IconBrandGithub className="h-4 w-4 text-neutral-800 dark:text-neutral-300" />
138+
<span className="text-sm text-neutral-700 dark:text-neutral-300">
139+
GitHub
140+
</span>
141+
<BottomGradient />
142+
</button>
143+
</div>
144+
</form>
145+
</div>
52146
)
53147
}

src/app/api/answer/route.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { answerCollection } from "@/models/name";
2+
import { databases, users } from "@/models/server/config";
3+
import { NextRequest, NextResponse } from "next/server";
4+
import { ID } from "node-appwrite";
5+
import { db } from "@/models/name";
6+
import {UserPrefs} from "@/store/Auth";
7+
8+
export async function POST(request: NextRequest){
9+
try {
10+
const {questionId, content, authorId} = await request.json();
11+
12+
const response = await databases.createDocument(db, answerCollection, ID.unique(),
13+
{
14+
content: content,
15+
authorId: authorId,
16+
questionId: questionId
17+
})
18+
//increase author rputation
19+
const prefs = await users.getPrefs<UserPrefs>(authorId)
20+
await users.updatePrefs(authorId,
21+
{reputation: Number(prefs.reputation) + 1}
22+
)
23+
return NextResponse.json(response,{
24+
status: 201
25+
});
26+
27+
} catch (error: any) {
28+
console.error(error);
29+
return NextResponse.json(
30+
{
31+
error: error?.message || "error creating answer"
32+
},
33+
{
34+
status: error?.status || error?.code || 500
35+
}
36+
)
37+
}
38+
}
39+
40+
export async function DELETE(request: NextRequest){
41+
try {
42+
const {answerId} = await request.json();
43+
const answer = await databases.getDocument(db, answerCollection, answerId);
44+
if(!answer) throw {status: 404, message: "answer not found"}
45+
const response = await databases.deleteDocument(db, answerCollection, answerId);
46+
//decrease author reputation
47+
const prefs = await users.getPrefs<UserPrefs>(answer.authorId)
48+
await users.updatePrefs(answer.authorId,
49+
{reputation: Number(prefs.reputation) - 1}
50+
)
51+
return NextResponse.json(response,{
52+
status: 201
53+
});
54+
} catch (error:any) {
55+
56+
console.error(error);
57+
return NextResponse.json(
58+
{
59+
error: error?.message || "error deleting answer"
60+
},
61+
{
62+
status: error?.status || error?.code || 500
63+
}
64+
)
65+
}
66+
}

0 commit comments

Comments
 (0)