Skip to content

Commit

Permalink
feat: Add createdAt and updatedAt fields to Vote model
Browse files Browse the repository at this point in the history
  • Loading branch information
ttizze committed Jul 15, 2024
1 parent 0a00199 commit 62c88bf
Show file tree
Hide file tree
Showing 17 changed files with 639 additions and 446 deletions.
96 changes: 58 additions & 38 deletions web/app/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,66 @@
import type { User } from "@prisma/client";
import { Link } from "@remix-run/react";
import { TranslationLanguageSelect } from "./TranslationLanguageSelect";
import { Form, useSubmit } from "@remix-run/react";

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

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

export function Header({ user }: HeaderProps) {
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">
<h1 className="text-3xl font-bold text-gray-900">EveEve</h1>
<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>
</header>
);
}
export function Header({ user, language }: HeaderProps) {
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>
);
}
36 changes: 18 additions & 18 deletions web/app/components/ui/textarea.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import * as React from "react"
import * as React from "react";

import { cn } from "~/utils"
import { cn } from "~/utils";

export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}

const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}
{...props}
/>
)
}
)
Textarea.displayName = "Textarea"
({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
ref={ref}
{...props}
/>
);
},
);
Textarea.displayName = "Textarea";

export { Textarea }
export { Textarea };
59 changes: 48 additions & 11 deletions web/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,84 @@
import type { User } from "@prisma/client";
import { json } from "@remix-run/node";
import type { LoaderFunctionArgs, ActionFunctionArgs } from "@remix-run/node";
import type { LinksFunction } from "@remix-run/node";
import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react";
import tailwind from "~/tailwind.css?url";
import type { User } from "@prisma/client";
import { json } from "@remix-run/node";
import type { LoaderFunctionArgs } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import tailwind from "~/tailwind.css?url";
import { Header } from "./components/Header";
import { authenticator } from "./utils/auth.server";
import type { LinksFunction } from "@remix-run/node";
import { getSession, commitSession } from "~/utils/session.server";
import { redirect } from "@remix-run/node";
import { Form } from "@remix-run/react";

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

export const links: LinksFunction = () => [
{ rel: "stylesheet", href: tailwind },
{ rel: "stylesheet", href: tailwind },
];
export interface RootLoaderData {
user: UserWithoutPassword | null;
language: string;
}

export async function loader({ request }: LoaderFunctionArgs) {
const user = await authenticator.isAuthenticated(request);
const safeUser = user ? { ...user, password: undefined } : null;
return json<RootLoaderData>({ user: safeUser });

const session = await getSession(request.headers.get("Cookie"));
const language = session.get("language") || "ja";

return json(
{ user: safeUser, language },
{
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();
const language = formData.get("language");

if (typeof language === "string") {
session.set("language", language);
}


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

export function Layout({ children }: { children: React.ReactNode }) {
const data = useLoaderData<typeof loader>();
const user = data?.user as UserWithoutPassword | null;
const data = useLoaderData<typeof loader>();
const user = data?.user as UserWithoutPassword | null;

return (
<html lang="en">
<html lang={data.language}>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<Header user={user as UserWithoutPassword | null} />
<Header user={user as UserWithoutPassword | null} language={data.language}/>
{children}
<ScrollRestoration />
<Scripts />
Expand Down
10 changes: 1 addition & 9 deletions web/app/routes/_index/components/URLTranslationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ import {
useNavigation,
useSubmit,
} from "@remix-run/react";
import { useState } from "react";
import { z } from "zod";
import { Alert, AlertDescription } from "~/components/ui/alert";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import { TranslationLanguageSelect } from "./TranslationLanguageSelect";

const urlTranslationSchema = z.object({
url: z.string().url("有効なURLを入力してください"),
Expand All @@ -21,7 +19,6 @@ const urlTranslationSchema = z.object({

export function URLTranslationForm() {
const navigation = useNavigation();
const [targetLanguage, setTargetLanguage] = useState("ja");
const submit = useSubmit();

const actionData = useActionData<{
Expand Down Expand Up @@ -54,11 +51,6 @@ export function URLTranslationForm() {
required
className="flex-grow"
/>
<input type="hidden" name="targetLanguage" value={targetLanguage} />
<TranslationLanguageSelect
value={targetLanguage}
onChange={setTargetLanguage}
/>
<Button type="submit" disabled={navigation.state === "submitting"}>
{navigation.state === "submitting" ? "翻訳中..." : "翻訳開始"}
</Button>
Expand Down Expand Up @@ -91,4 +83,4 @@ export function URLTranslationForm() {
);
}

export { urlTranslationSchema };
export { urlTranslationSchema };
29 changes: 23 additions & 6 deletions web/app/routes/_index/components/translatedList.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
import type { Page } from "@prisma/client";
import { useLoaderData } from "@remix-run/react";
import type { PageVersion } from "@prisma/client";
import { useLoaderData, useMatches } from "@remix-run/react";
import type { RootLoaderData } from "~/root"; // root.tsxからインポート

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

export function TranslatedList() {
const { pageList } = useLoaderData<LoaderData>();
return <div>TranslatedList</div>;
}
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>
);
}
Loading

0 comments on commit 62c88bf

Please sign in to comment.