diff --git a/app/(dashboard)/feedback/page.tsx b/app/(dashboard)/feedback/page.tsx
index e180624..1197ad9 100644
--- a/app/(dashboard)/feedback/page.tsx
+++ b/app/(dashboard)/feedback/page.tsx
@@ -173,10 +173,10 @@ export default function FeedbackPage() {
}
function StatusBadge({ f }: { f: AdminFeedback }) {
- const label = f.replied_at
- ? "Replied"
- : f.resolved_at
- ? "Resolved"
+ const label = f.resolved_at
+ ? "Resolved"
+ : f.replied_at
+ ? "Replied"
: f.acknowledged_at
? "Acknowledged"
: "Open";
@@ -240,7 +240,7 @@ function ReplyModal({
onChange={(e) => setMessage(e.target.value)}
rows={5}
maxLength={4000}
- placeholder="Write your reply… (emailed to the submitter, marks this resolved)"
+ placeholder="Write your reply… (emailed to the submitter; use Resolve separately to close it)"
/>
diff --git a/app/(dashboard)/users/page.tsx b/app/(dashboard)/users/page.tsx
index 2d4f2e8..5911e71 100644
--- a/app/(dashboard)/users/page.tsx
+++ b/app/(dashboard)/users/page.tsx
@@ -1,8 +1,10 @@
"use client";
import { useCallback, useState } from "react";
+import { Mail } from "lucide-react";
import { toast } from "sonner";
import { api, AdminError, type AdminUser } from "@/lib/api";
+import { GoogleIcon, FacebookIcon } from "@/components/ui/provider-icons";
import { usePagedList } from "@/lib/use-paged-list";
import { ListShell, EmptyRow } from "@/components/list-shell";
import { Table, THead, TR, TH, TD } from "@/components/ui/table";
@@ -74,6 +76,7 @@ export default function UsersPage() {
| User |
Email |
+ Auth |
Posts |
Joined |
Actions |
@@ -81,7 +84,7 @@ export default function UsersPage() {
{list.items.length === 0 && !list.loading ? (
-
+
) : (
list.items.map((u) => (
@@ -106,6 +109,9 @@ export default function UsersPage() {
|
{u.email ?? —}
|
+
+
+ |
{u.post_count} |
{fmtDate(u.created_at)} |
@@ -122,6 +128,38 @@ export default function UsersPage() {
);
}
+function AuthIcons({ user }: { user: AdminUser }) {
+ const hasGoogle = user.providers.includes("google");
+ const hasFacebook = user.providers.includes("facebook");
+ if (!user.has_password && !hasGoogle && !hasFacebook) {
+ return —;
+ }
+ return (
+
+ {user.has_password ? (
+ // Tooltip shows the email on hover; clicking copies it to the clipboard.
+
+ ) : null}
+ {hasGoogle ? : null}
+ {hasFacebook ? : null}
+
+ );
+}
+
function NotifyModal({
user,
onClose,
diff --git a/components/ui/provider-icons.tsx b/components/ui/provider-icons.tsx
new file mode 100644
index 0000000..40692f1
--- /dev/null
+++ b/components/ui/provider-icons.tsx
@@ -0,0 +1,33 @@
+// Brand glyphs for OAuth providers. lucide-react dropped brand icons, so these
+// are small inline SVGs (Google's multicolour "G", Facebook's blue "f").
+
+export function GoogleIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
+
+export function FacebookIcon({ className }: { className?: string }) {
+ return (
+
+ );
+}
diff --git a/lib/api.ts b/lib/api.ts
index ff9d81f..c1a7b62 100644
--- a/lib/api.ts
+++ b/lib/api.ts
@@ -104,6 +104,8 @@ export type AdminUser = {
banned_at: string | null;
post_count: number;
created_at: string;
+ has_password: boolean;
+ providers: string[];
};
export type AdminPost = {
|