aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend/src/pages
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-12-03 03:51:29 +0900
committernsfisis <nsfisis@gmail.com>2025-12-04 23:27:28 +0900
commit58d132139ba8d5fa17c8681a0275047ce4cca809 (patch)
tree7dd18f5de496483b7d318e12e43379a51f3a6056 /frontend/src/pages
parentaac4e9ccdebe52c156506d1899d5a38e99366f69 (diff)
downloadfeedaka-58d132139ba8d5fa17c8681a0275047ce4cca809.tar.gz
feedaka-58d132139ba8d5fa17c8681a0275047ce4cca809.tar.zst
feedaka-58d132139ba8d5fa17c8681a0275047ce4cca809.zip
feat(frontend): design update
Diffstat (limited to 'frontend/src/pages')
-rw-r--r--frontend/src/pages/Login.tsx101
-rw-r--r--frontend/src/pages/NotFound.tsx16
-rw-r--r--frontend/src/pages/ReadArticles.tsx18
-rw-r--r--frontend/src/pages/Settings.tsx21
-rw-r--r--frontend/src/pages/UnreadArticles.tsx20
5 files changed, 104 insertions, 72 deletions
diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx
index 4d81234..76a775a 100644
--- a/frontend/src/pages/Login.tsx
+++ b/frontend/src/pages/Login.tsx
@@ -25,51 +25,64 @@ export function Login() {
};
return (
- <div className="flex justify-center items-center min-h-screen bg-gray-100">
- <div className="bg-white p-8 rounded-lg shadow w-full max-w-md">
- <h1 className="mb-6 text-center text-2xl font-bold">Feedaka Login</h1>
- <form onSubmit={handleSubmit}>
- <div className="mb-4">
- <label htmlFor="username" className="block mb-2">
- Username
- </label>
- <input
- id="username"
- type="text"
- value={username}
- onChange={(e) => setUsername(e.target.value)}
- required
- className="w-full p-2 border border-gray-300 rounded disabled:opacity-70 disabled:cursor-not-allowed"
- disabled={isLoading}
- />
- </div>
- <div className="mb-4">
- <label htmlFor="password" className="block mb-2">
- Password
- </label>
- <input
- id="password"
- type="password"
- value={password}
- onChange={(e) => setPassword(e.target.value)}
- required
- className="w-full p-2 border border-gray-300 rounded disabled:opacity-70 disabled:cursor-not-allowed"
- disabled={isLoading}
- />
- </div>
- {error && (
- <div className="text-red-600 mb-4 p-2 bg-red-50 rounded">
- {error}
+ <div className="flex min-h-screen items-center justify-center bg-gradient-to-br from-stone-100 to-stone-50 px-4">
+ <div className="w-full max-w-sm">
+ <div className="mb-8 text-center">
+ <h1 className="text-2xl font-semibold tracking-tight text-stone-900">
+ feedaka
+ </h1>
+ <p className="mt-2 text-sm text-stone-500">Sign in to your account</p>
+ </div>
+ <div className="rounded-xl border border-stone-200 bg-white p-6 shadow-sm">
+ <form onSubmit={handleSubmit} className="space-y-5">
+ <div>
+ <label
+ htmlFor="username"
+ className="mb-1.5 block text-sm font-medium text-stone-700"
+ >
+ Username
+ </label>
+ <input
+ id="username"
+ type="text"
+ value={username}
+ onChange={(e) => setUsername(e.target.value)}
+ required
+ className="w-full rounded-lg border border-stone-200 bg-white px-4 py-2.5 text-sm text-stone-900 transition-all duration-200 placeholder:text-stone-400 focus:border-sky-500 focus:outline-none focus:ring-2 focus:ring-sky-500/20 disabled:cursor-not-allowed disabled:opacity-70"
+ disabled={isLoading}
+ />
</div>
- )}
- <button
- type="submit"
- disabled={isLoading}
- className="w-full p-3 bg-blue-500 text-white rounded cursor-pointer hover:bg-blue-600 disabled:opacity-70 disabled:cursor-not-allowed"
- >
- {isLoading ? "Logging in..." : "Login"}
- </button>
- </form>
+ <div>
+ <label
+ htmlFor="password"
+ className="mb-1.5 block text-sm font-medium text-stone-700"
+ >
+ Password
+ </label>
+ <input
+ id="password"
+ type="password"
+ value={password}
+ onChange={(e) => setPassword(e.target.value)}
+ required
+ className="w-full rounded-lg border border-stone-200 bg-white px-4 py-2.5 text-sm text-stone-900 transition-all duration-200 placeholder:text-stone-400 focus:border-sky-500 focus:outline-none focus:ring-2 focus:ring-sky-500/20 disabled:cursor-not-allowed disabled:opacity-70"
+ disabled={isLoading}
+ />
+ </div>
+ {error && (
+ <div className="rounded-lg bg-red-50 p-3 text-sm text-red-600">
+ {error}
+ </div>
+ )}
+ <button
+ type="submit"
+ disabled={isLoading}
+ className="w-full rounded-lg bg-sky-600 px-4 py-2.5 text-sm font-medium text-white transition-all duration-200 hover:bg-sky-700 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-70"
+ >
+ {isLoading ? "Signing in..." : "Sign in"}
+ </button>
+ </form>
+ </div>
</div>
</div>
);
diff --git a/frontend/src/pages/NotFound.tsx b/frontend/src/pages/NotFound.tsx
index 23c1184..adc782b 100644
--- a/frontend/src/pages/NotFound.tsx
+++ b/frontend/src/pages/NotFound.tsx
@@ -1,14 +1,24 @@
+import { Link } from "wouter";
+
export function NotFound() {
return (
<div className="flex min-h-96 flex-col items-center justify-center">
<div className="text-center">
- <h1 className="text-6xl font-bold text-gray-900">404</h1>
- <h2 className="mt-4 text-2xl font-semibold text-gray-700">
+ <h1 className="text-6xl font-semibold tracking-tight text-stone-900">
+ 404
+ </h1>
+ <h2 className="mt-4 text-xl font-medium text-stone-700">
Page Not Found
</h2>
- <p className="mt-2 text-gray-500">
+ <p className="mt-2 text-sm text-stone-400">
The page you're looking for doesn't exist.
</p>
+ <Link
+ href="/"
+ className="mt-6 inline-block rounded-lg bg-sky-600 px-5 py-2.5 text-sm font-medium text-white transition-all duration-200 hover:bg-sky-700"
+ >
+ Go back home
+ </Link>
</div>
</div>
);
diff --git a/frontend/src/pages/ReadArticles.tsx b/frontend/src/pages/ReadArticles.tsx
index ccbd2dc..f90c3c9 100644
--- a/frontend/src/pages/ReadArticles.tsx
+++ b/frontend/src/pages/ReadArticles.tsx
@@ -11,19 +11,27 @@ export function ReadArticles() {
});
if (fetching) {
- return <div className="p-4">Loading read articles...</div>;
+ return (
+ <div className="py-8 text-center">
+ <p className="text-sm text-stone-400">Loading read articles...</p>
+ </div>
+ );
}
if (error) {
- return <div className="p-4 text-red-600">Error: {error.message}</div>;
+ return (
+ <div className="rounded-lg bg-red-50 p-4 text-sm text-red-600">
+ Error: {error.message}
+ </div>
+ );
}
return (
<div>
- <div className="border-b border-gray-200 bg-white px-4 py-3">
- <h1 className="text-xl font-semibold text-gray-900">Read Articles</h1>
+ <div className="mb-6">
+ <h1 className="text-xl font-semibold text-stone-900">Read</h1>
{data?.readArticles && (
- <p className="text-sm text-gray-500">
+ <p className="mt-1 text-sm text-stone-400">
{data.readArticles.length} article
{data.readArticles.length !== 1 ? "s" : ""}
</p>
diff --git a/frontend/src/pages/Settings.tsx b/frontend/src/pages/Settings.tsx
index b10cbf1..9b1e04c 100644
--- a/frontend/src/pages/Settings.tsx
+++ b/frontend/src/pages/Settings.tsx
@@ -16,24 +16,17 @@ export function Settings() {
};
return (
- <div className="mx-auto max-w-4xl">
- <h1 className="mb-6 text-2xl font-bold text-gray-900">Feed Settings</h1>
-
- {/* Subscribe to New Feed Section */}
- <div className="mb-8">
- <h2 className="mb-4 text-xl font-semibold text-gray-800">
- Subscribe to New Feed
- </h2>
+ <div className="mx-auto max-w-3xl space-y-10">
+ <section>
<AddFeedForm onFeedAdded={handleFeedAdded} />
- </div>
+ </section>
- {/* Manage Feeds Section */}
- <div className="mb-8">
- <h2 className="mb-4 text-xl font-semibold text-gray-800">
- Manage Feeds
+ <section>
+ <h2 className="mb-4 text-sm font-semibold uppercase tracking-wide text-stone-900">
+ Your Feeds
</h2>
<FeedList onFeedUnsubscribed={handleFeedUnsubscribed} />
- </div>
+ </section>
</div>
);
}
diff --git a/frontend/src/pages/UnreadArticles.tsx b/frontend/src/pages/UnreadArticles.tsx
index dc4c377..28cc8b5 100644
--- a/frontend/src/pages/UnreadArticles.tsx
+++ b/frontend/src/pages/UnreadArticles.tsx
@@ -11,21 +11,29 @@ export function UnreadArticles() {
});
if (fetching) {
- return <div className="p-4">Loading unread articles...</div>;
+ return (
+ <div className="py-8 text-center">
+ <p className="text-sm text-stone-400">Loading unread articles...</p>
+ </div>
+ );
}
if (error) {
- return <div className="p-4 text-red-600">Error: {error.message}</div>;
+ return (
+ <div className="rounded-lg bg-red-50 p-4 text-sm text-red-600">
+ Error: {error.message}
+ </div>
+ );
}
return (
<div>
- <div className="border-b border-gray-200 bg-white px-4 py-3">
- <h1 className="text-xl font-semibold text-gray-900">Unread Articles</h1>
+ <div className="mb-6">
+ <h1 className="text-xl font-semibold text-stone-900">Unread</h1>
{data?.unreadArticles && (
- <p className="text-sm text-gray-500">
+ <p className="mt-1 text-sm text-stone-400">
{data.unreadArticles.length} article
- {data.unreadArticles.length !== 1 ? "s" : ""}
+ {data.unreadArticles.length !== 1 ? "s" : ""} to read
</p>
)}
</div>