Skip to content

Commit

Permalink
chore: Update URLTranslationForm and VoteButtons components (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
ttizze authored Jul 15, 2024
1 parent 8a01789 commit 0021195
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 113 deletions.
113 changes: 58 additions & 55 deletions web/app/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,69 @@
import type { User } from "@prisma/client";
import { Link } from "@remix-run/react";
import { TranslationLanguageSelect } from "./TranslationLanguageSelect";
import { Form, useSubmit } from "@remix-run/react";
import { TranslationLanguageSelect } from "./TranslationLanguageSelect";

type UserWithoutPassword = Omit<User, "password">;

interface HeaderProps {
user: UserWithoutPassword | null;
language: string;
user: UserWithoutPassword | null;
language: string;
}

export function Header({ user, language }: HeaderProps) {
const submit = useSubmit();
const submit = useSubmit();

const handleLanguageChange = (newLanguage: string) => {
const formData = new FormData();
formData.append("language", newLanguage);
submit(formData, { method: "post" });
};
return (
<header className="bg-white shadow-sm">
<div className="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8 flex justify-between items-center">
<Link to="/">
<h1 className="text-3xl font-bold text-gray-900">EveEve</h1>
</Link>
<div className="flex items-center space-x-4">
<Form method="post">
<TranslationLanguageSelect
value={language}
onChange={handleLanguageChange}
/>
</Form>
<nav>
{user ? (
<div className="flex items-center space-x-4">
<span className="text-gray-700">ようこそ、{user.name}さん!</span>
<Link
to="/auth/logout"
className="text-blue-600 hover:text-blue-800 font-medium"
>
ログアウト
</Link>
</div>
) : (
<div className="space-x-4">
<Link
to="/auth/login"
className="text-blue-600 hover:text-blue-800 font-medium"
>
ログイン
</Link>
<Link
to="/auth/signup"
className="text-blue-600 hover:text-blue-800 font-medium"
>
サインアップ
</Link>
</div>
)}
</nav>
</div>
</div>
</header>
);
}
const handleLanguageChange = (newLanguage: string) => {
const formData = new FormData();
formData.append("language", newLanguage);
submit(formData, { method: "post" });
};

return (
<header className="bg-white shadow-sm">
<div className="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8 flex justify-between items-center">
<Link to="/">
<h1 className="text-3xl font-bold text-gray-900">EveEve</h1>
</Link>
<div className="flex items-center space-x-4">
<Form method="post">
<TranslationLanguageSelect
value={language}
onChange={handleLanguageChange}
/>
</Form>
<nav>
{user ? (
<div className="flex items-center space-x-4">
<span className="text-gray-700">
ようこそ、{user.name}さん!
</span>
<Link
to="/auth/logout"
className="text-blue-600 hover:text-blue-800 font-medium"
>
ログアウト
</Link>
</div>
) : (
<div className="space-x-4">
<Link
to="/auth/login"
className="text-blue-600 hover:text-blue-800 font-medium"
>
ログイン
</Link>
<Link
to="/auth/signup"
className="text-blue-600 hover:text-blue-800 font-medium"
>
サインアップ
</Link>
</div>
)}
</nav>
</div>
</div>
</header>
);
}
31 changes: 15 additions & 16 deletions web/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { User } from "@prisma/client";
import { json } from "@remix-run/node";
import type { LoaderFunctionArgs, ActionFunctionArgs } from "@remix-run/node";
import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node";
import type { LinksFunction } from "@remix-run/node";
import {
Links,
Expand All @@ -11,11 +11,9 @@ import {
} from "@remix-run/react";
import { useLoaderData } from "@remix-run/react";
import tailwind from "~/tailwind.css?url";
import { commitSession, getSession } from "~/utils/session.server";
import { Header } from "./components/Header";
import { authenticator } from "./utils/auth.server";
import { getSession, commitSession } from "~/utils/session.server";
import { redirect } from "@remix-run/node";
import { Form } from "@remix-run/react";

type UserWithoutPassword = Omit<User, "password">;

Expand All @@ -40,11 +38,10 @@ export async function loader({ request }: LoaderFunctionArgs) {
headers: {
"Set-Cookie": await commitSession(session),
},
}
},
);
}


export async function action({ request }: ActionFunctionArgs) {
const session = await getSession(request.headers.get("Cookie"));
const formData = await request.formData();
Expand All @@ -54,15 +51,14 @@ export async function action({ request }: ActionFunctionArgs) {
session.set("language", language);
}


return json(
{ success: true },
{
headers: {
"Set-Cookie": await commitSession(session),
},
}
);
return json(
{ success: true },
{
headers: {
"Set-Cookie": await commitSession(session),
},
},
);
}

export function Layout({ children }: { children: React.ReactNode }) {
Expand All @@ -78,7 +74,10 @@ export function Layout({ children }: { children: React.ReactNode }) {
<Links />
</head>
<body>
<Header user={user as UserWithoutPassword | null} language={data.language}/>
<Header
user={user as UserWithoutPassword | null}
language={data.language}
/>
{children}
<ScrollRestoration />
<Scripts />
Expand Down
2 changes: 1 addition & 1 deletion web/app/routes/_index/components/URLTranslationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,4 @@ export function URLTranslationForm() {
);
}

export { urlTranslationSchema };
export { urlTranslationSchema };
38 changes: 19 additions & 19 deletions web/app/routes/_index/components/translatedList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@ import { useLoaderData, useMatches } from "@remix-run/react";
import type { RootLoaderData } from "~/root"; // root.tsxからインポート

interface LoaderData {
pageVersionList: PageVersion[];
pageVersionList: PageVersion[];
}

export function TranslatedList() {
const { pageVersionList } = useLoaderData<LoaderData>();
const matches = useMatches();
const rootData = matches[0].data as RootLoaderData;
const language = rootData.language;
const { pageVersionList } = useLoaderData<LoaderData>();
const matches = useMatches();
const rootData = matches[0].data as RootLoaderData;
const language = rootData.language;

return (
<div>
<h2>Translated List (Language: {language})</h2>
<ul>
{pageVersionList.map((pageVersion) => (
<li key={pageVersion.id}>
{/* ページのタイトルや他の情報を表示 */}
{pageVersion.title} - {pageVersion.url}
</li>
))}
</ul>
</div>
);
}
return (
<div>
<h2>Translated List (Language: {language})</h2>
<ul>
{pageVersionList.map((pageVersion) => (
<li key={pageVersion.id}>
{/* ページのタイトルや他の情報を表示 */}
{pageVersion.title} - {pageVersion.url}
</li>
))}
</ul>
</div>
);
}
33 changes: 22 additions & 11 deletions web/app/routes/reader.$encodedUrl/components/Translation.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Edit, Plus, X } from "lucide-react";
import { Save, Trash } from "lucide-react";
import { useCallback, useMemo, useState } from "react";
import { Button } from "~/components/ui/button";
import { Textarea } from "~/components/ui/textarea";
import { useClickOutside } from "../hooks/useClickOutside";
import type { TranslationData } from "../types";
import { VoteButtons } from "./VoteButtons";
import { Save, Trash } from "lucide-react";

interface TranslationProps {
translations: TranslationData[];
Expand Down Expand Up @@ -69,7 +69,9 @@ export function Translation({
lang={targetLanguage}
className="notranslate mt-2 p-4 bg-gray-50 rounded-lg shadow-sm border border-gray-200 group relative"
>
<div className="text-lg font-medium text-gray-800">{bestTranslation.text}</div>
<div className="text-lg font-medium text-gray-800">
{bestTranslation.text}
</div>
<Button
variant="outline"
size="sm"
Expand All @@ -83,17 +85,22 @@ export function Translation({
</Button>
{isExpanded && (
<div className="">
<VoteButtons
translation={bestTranslation}
onVote={handleVote}
userId={userId}
/>
<VoteButtons
translation={bestTranslation}
onVote={handleVote}
userId={userId}
/>
{alternativeTranslations.length > 0 && (
<div className=" rounded-md">
<p className="font-semibold text-gray-600 mb-2">Other translations:</p>
<p className="font-semibold text-gray-600 mb-2">
Other translations:
</p>
<div className="space-y-3">
{alternativeTranslations.map((alt) => (
<div key={alt.id} className="p-2 bg-gray-50 rounded border border-gray-200">
<div
key={alt.id}
className="p-2 bg-gray-50 rounded border border-gray-200"
>
<div className="text-sm text-gray-700 mb-2">{alt.text}</div>
<VoteButtons
translation={alt}
Expand All @@ -114,7 +121,11 @@ export function Translation({
onClick={() => setIsEditing(!isEditing)}
className="text-blue-600 hover:bg-blue-50"
>
{isEditing ? <X className="h-4 w-4" /> : <Edit className="h-4 w-4" />}
{isEditing ? (
<X className="h-4 w-4" />
) : (
<Edit className="h-4 w-4" />
)}
</Button>
</div>
{isEditing && (
Expand Down Expand Up @@ -151,4 +162,4 @@ export function Translation({
)}
</div>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ export function VoteButtons({ translation, onVote, userId }: VoteButtonsProps) {
</div>
</div>
);
}
}
2 changes: 1 addition & 1 deletion web/app/routes/reader.$encodedUrl/hooks/useClickOutside.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const useClickOutside = (callback: () => void) => {
const ref = useRef<HTMLDivElement>(null);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
const handleClickOutside = (event: MouseEvent | TouchEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
callback();
}
Expand Down
5 changes: 5 additions & 0 deletions web/app/routes/reader.$encodedUrl/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ import { TranslatedContent } from "./components/TranslatedContent";
import type { TranslationData } from "./types";
import { fetchLatestPageVersionWithTranslations } from "./utils";
import { handleAddTranslationAction, handleVoteAction } from "./utils/actions";
import { getSession } from "~/utils/session.server";

export const loader = async ({ params, request }: LoaderFunctionArgs) => {
const session = await getSession(request.headers.get("Cookie"));
const language = session.get("language") || "ja";

const { encodedUrl } = params;
if (!encodedUrl) {
throw new Response("Missing URL parameter", { status: 400 });
Expand All @@ -21,6 +25,7 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
const pageData = await fetchLatestPageVersionWithTranslations(
decodeURIComponent(encodedUrl),
userId ?? 0,
language,
);

if (!pageData) {
Expand Down
3 changes: 2 additions & 1 deletion web/app/routes/reader.$encodedUrl/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { LoaderData, SourceTextTranslations } from "./types";
export async function fetchLatestPageVersionWithTranslations(
url: string,
userId: number | null,
language: string,
): Promise<LoaderData | null> {
const pageVersion = await prisma.pageVersion.findFirst({
where: { url },
Expand All @@ -16,7 +17,7 @@ export async function fetchLatestPageVersionWithTranslations(
select: {
number: true,
translateTexts: {
where: { language: "ja" },
where: { language },
select: {
id: true,
text: true,
Expand Down
Loading

0 comments on commit 0021195

Please sign in to comment.