feat: update frontend to work with v2 backend — camelCase, new endpoints, nested author
Some checks failed
lint / lint (push) Has been cancelled
test / unit (push) Has been cancelled
test / integration (push) Has been cancelled
lint / lint (pull_request) Failing after 9m38s
test / unit (pull_request) Successful in 16m2s
test / integration (pull_request) Failing after 17m2s
Some checks failed
lint / lint (push) Has been cancelled
test / unit (push) Has been cancelled
test / integration (push) Has been cancelled
lint / lint (pull_request) Failing after 9m38s
test / unit (pull_request) Successful in 16m2s
test / integration (pull_request) Failing after 17m2s
This commit is contained in:
@@ -33,7 +33,7 @@ export default function LoginPage() {
|
||||
|
||||
const form = useForm<z.infer<typeof LoginSchema>>({
|
||||
resolver: zodResolver(LoginSchema),
|
||||
defaultValues: { username: "", password: "" },
|
||||
defaultValues: { email: "", password: "" },
|
||||
});
|
||||
|
||||
async function onSubmit(values: z.infer<typeof LoginSchema>) {
|
||||
@@ -43,7 +43,7 @@ export default function LoginPage() {
|
||||
setToken(token);
|
||||
router.push("/"); // Redirect to homepage on successful login
|
||||
} catch {
|
||||
setError("Invalid username or password.");
|
||||
setError("Invalid email or password.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,12 +61,12 @@ export default function LoginPage() {
|
||||
{/* ... Form fields for username and password ... */}
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="username"
|
||||
name="email"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormLabel>Email</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="frutiger" {...field} />
|
||||
<Input type="email" placeholder="you@example.com" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
getFeed,
|
||||
getFriends,
|
||||
getMe,
|
||||
getTopFriends,
|
||||
getUserProfile,
|
||||
Me,
|
||||
User,
|
||||
@@ -60,7 +61,7 @@ async function FeedPage({
|
||||
const { items: allThoughts, totalPages } = feedData!;
|
||||
const thoughtThreads = buildThoughtThreads(allThoughts);
|
||||
|
||||
const authors = [...new Set(allThoughts.map((t) => t.authorUsername))];
|
||||
const authors = [...new Set(allThoughts.map((t) => t.author.username))];
|
||||
const userProfiles = await Promise.all(
|
||||
authors.map((username) => getUserProfile(username, token).catch(() => null))
|
||||
);
|
||||
@@ -72,10 +73,10 @@ async function FeedPage({
|
||||
);
|
||||
|
||||
const friends = (await getFriends(token)).users.map((user) => user.username);
|
||||
const shouldDisplayTopFriends =
|
||||
token && me?.topFriends && me.topFriends.length > 8;
|
||||
|
||||
console.log("Should display top friends:", shouldDisplayTopFriends);
|
||||
const topFriendsData = me
|
||||
? await getTopFriends(me.username, token).catch(() => ({ topFriends: [] }))
|
||||
: { topFriends: [] };
|
||||
const shouldDisplayTopFriends = topFriendsData.topFriends.length > 0;
|
||||
|
||||
return (
|
||||
<div className="container mx-auto max-w-6xl p-4 sm:p-6">
|
||||
@@ -96,7 +97,7 @@ async function FeedPage({
|
||||
<div className="block lg:hidden space-y-6">
|
||||
<PopularTags />
|
||||
{shouldDisplayTopFriends && (
|
||||
<TopFriends mode="top-friends" usernames={me.topFriends} />
|
||||
<TopFriends mode="top-friends" usernames={topFriendsData.topFriends} />
|
||||
)}
|
||||
{!shouldDisplayTopFriends && token && friends.length > 0 && (
|
||||
<TopFriends mode="friends" usernames={friends || []} />
|
||||
@@ -141,7 +142,7 @@ async function FeedPage({
|
||||
<div className="sticky top-20 space-y-6">
|
||||
<PopularTags />
|
||||
{shouldDisplayTopFriends && (
|
||||
<TopFriends mode="top-friends" usernames={me.topFriends} />
|
||||
<TopFriends mode="top-friends" usernames={topFriendsData.topFriends} />
|
||||
)}
|
||||
{!shouldDisplayTopFriends && token && friends.length > 0 && (
|
||||
<TopFriends mode="friends" usernames={friends || []} />
|
||||
|
||||
@@ -30,7 +30,7 @@ export default async function SearchPage({ searchParams }: SearchPageProps) {
|
||||
|
||||
const authorDetails = new Map<string, { avatarUrl?: string | null }>();
|
||||
if (results) {
|
||||
results.users.users.forEach((user: User) => {
|
||||
results.users.forEach((user: User) => {
|
||||
authorDetails.set(user.username, { avatarUrl: user.avatarUrl });
|
||||
});
|
||||
}
|
||||
@@ -48,21 +48,21 @@ export default async function SearchPage({ searchParams }: SearchPageProps) {
|
||||
<Tabs defaultValue="thoughts" className="w-full">
|
||||
<TabsList>
|
||||
<TabsTrigger value="thoughts">
|
||||
Thoughts ({results.thoughts.thoughts.length})
|
||||
Thoughts ({results.thoughts.length})
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="users">
|
||||
Users ({results.users.users.length})
|
||||
Users ({results.users.length})
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="thoughts">
|
||||
<ThoughtList
|
||||
thoughts={results.thoughts.thoughts}
|
||||
thoughts={results.thoughts}
|
||||
authorDetails={authorDetails}
|
||||
currentUser={me}
|
||||
/>
|
||||
</TabsContent>
|
||||
<TabsContent value="users">
|
||||
<UserListCard users={results.users.users} />
|
||||
<UserListCard users={results.users} />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
) : (
|
||||
|
||||
@@ -10,7 +10,7 @@ export default async function ApiKeysPage() {
|
||||
}
|
||||
|
||||
const initialApiKeys = await getApiKeys(token).catch(() => ({
|
||||
apiKeys: [],
|
||||
keys: [],
|
||||
}));
|
||||
|
||||
return (
|
||||
@@ -21,7 +21,7 @@ export default async function ApiKeysPage() {
|
||||
Manage API keys for third-party applications.
|
||||
</p>
|
||||
</div>
|
||||
<ApiKeyList initialApiKeys={initialApiKeys.apiKeys} />
|
||||
<ApiKeyList initialApiKeys={initialApiKeys.keys} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ export default async function TagPage({ params }: TagPageProps) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const allThoughts = thoughtsResult.value.thoughts;
|
||||
const allThoughts = thoughtsResult.value.items;
|
||||
const thoughtThreads = buildThoughtThreads(allThoughts);
|
||||
const me = meResult.status === "fulfilled" ? (meResult.value as Me) : null;
|
||||
|
||||
const authors = [...new Set(allThoughts.map((t) => t.authorUsername))];
|
||||
const authors = [...new Set(allThoughts.map((t) => t.author.username))];
|
||||
const userProfiles = await Promise.all(
|
||||
authors.map((username) => getUserProfile(username, token).catch(() => null))
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ interface ThoughtPageProps {
|
||||
}
|
||||
|
||||
function collectAuthors(thread: ThoughtThreadType): string[] {
|
||||
const authors = new Set<string>([thread.authorUsername]);
|
||||
const authors = new Set<string>([thread.author.username]);
|
||||
for (const reply of thread.replies) {
|
||||
collectAuthors(reply).forEach((author) => authors.add(author));
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export default async function FollowersPage({ params }: FollowersPageProps) {
|
||||
<p className="text-muted-foreground">Users following @{username}.</p>
|
||||
</header>
|
||||
<main>
|
||||
<UserListCard users={followersData.users} />
|
||||
<UserListCard users={followersData.items} />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -26,7 +26,7 @@ export default async function FollowingPage({ params }: FollowingPageProps) {
|
||||
<p className="text-muted-foreground">Users that @{username} follows.</p>
|
||||
</header>
|
||||
<main>
|
||||
<UserListCard users={followingData.users} />
|
||||
<UserListCard users={followingData.items} />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
getFollowingList,
|
||||
getFriends,
|
||||
getMe,
|
||||
getTopFriends,
|
||||
getUserProfile,
|
||||
getUserThoughts,
|
||||
Me,
|
||||
@@ -55,33 +56,31 @@ export default async function ProfilePage({ params }: ProfilePageProps) {
|
||||
const me = meResult.status === "fulfilled" ? (meResult.value as Me) : null;
|
||||
|
||||
const thoughts =
|
||||
thoughtsResult.status === "fulfilled" ? thoughtsResult.value.thoughts : [];
|
||||
thoughtsResult.status === "fulfilled" ? thoughtsResult.value.items : [];
|
||||
const thoughtThreads = buildThoughtThreads(thoughts);
|
||||
|
||||
const followersCount =
|
||||
followersResult.status === "fulfilled"
|
||||
? followersResult.value.users.length
|
||||
? followersResult.value.total
|
||||
: 0;
|
||||
const followingCount =
|
||||
followingResult.status === "fulfilled"
|
||||
? followingResult.value.users.length
|
||||
? followingResult.value.total
|
||||
: 0;
|
||||
|
||||
const isOwnProfile = me?.username === user.username;
|
||||
const isFollowing =
|
||||
me?.following?.some(
|
||||
(followedUser) => followedUser.username === user.username
|
||||
) || false;
|
||||
const isFollowing = user.isFollowedByViewer;
|
||||
|
||||
const authorDetails = new Map<string, { avatarUrl?: string | null }>();
|
||||
authorDetails.set(user.username, { avatarUrl: user.avatarUrl });
|
||||
|
||||
const friends =
|
||||
typeof token === "string"
|
||||
? (await getFriends(token)).users.map((user) => user.username)
|
||||
? (await getFriends(token)).users.map((u) => u.username)
|
||||
: [];
|
||||
|
||||
const shouldDisplayTopFriends = token && friends.length > 8;
|
||||
const topFriendsData = await getTopFriends(username, token).catch(() => ({ topFriends: [] }));
|
||||
const shouldDisplayTopFriends = topFriendsData.topFriends.length > 0;
|
||||
|
||||
return (
|
||||
<div id={`profile-page-${user.username}`}>
|
||||
@@ -195,7 +194,7 @@ export default async function ProfilePage({ params }: ProfilePageProps) {
|
||||
</Card>
|
||||
|
||||
{shouldDisplayTopFriends && (
|
||||
<TopFriends mode="top-friends" usernames={user.topFriends} />
|
||||
<TopFriends mode="top-friends" usernames={topFriendsData.topFriends} />
|
||||
)}
|
||||
{token && <TopFriends mode="friends" usernames={friends || []} />}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user