Create Top page

This commit is contained in:
Takeshi Kimata
2024-05-11 15:59:31 +09:00
parent 64739ff837
commit 76076f2c48
6 changed files with 164 additions and 20 deletions

View File

@@ -3,8 +3,18 @@
"get_started": "Get Started", "get_started": "Get Started",
"oss_tcmt": "Open Source Test Case Management Tool", "oss_tcmt": "Open Source Test Case Management Tool",
"integrate_and_manage": "Integrate and manage all your software testing.", "integrate_and_manage": "Integrate and manage all your software testing.",
"features": "Features", "oss_title": "Open Source",
"demo_screen": "Demo Screen" "oss_detail": "TestPlat is free and open source. The application can be self-hosted. It can be deployed in environments with strict security requirements.",
"organize_title": "Organize Test Cases",
"organize_detail": "Test cases can be organized by projects and folders. Modern UI framework makes them fast.",
"usability_title": "Usability",
"usability_detail": "The defined test cases can be used over and over again in test runs. The status of test runs and projects can be viewed graphically.",
"universal_title": "Universal",
"universal_detail": "Multi language support and dark theme allow anyone to use the system without any inconvenience.",
"organize_test_cases": "Organize test cases and manage tests graphically",
"self_host": "Self host the application",
"run_as_docker": "Running TestPlat as a Docker container",
"run_by_manually": "Running TestPlat manually"
}, },
"Header": { "Header": {
"title": "Open Source Test Case Management Tool", "title": "Open Source Test Case Management Tool",

View File

@@ -3,8 +3,18 @@
"get_started": "テスト管理を始める", "get_started": "テスト管理を始める",
"oss_tcmt": "オープンソーステストケース管理ツール", "oss_tcmt": "オープンソーステストケース管理ツール",
"integrate_and_manage": "ソフトウェア開発にかかわるすべてのテストを統合管理", "integrate_and_manage": "ソフトウェア開発にかかわるすべてのテストを統合管理",
"features": "機能", "oss_title": "オープンソース",
"demo_screen": "デモ画面" "oss_detail": "TestPlatは無料でオープンソースです。アプリケーションをセルフホストすることができます。セキュリティ要件の厳しい環境でも導入することができます。",
"organize_title": "テストケースの整理",
"organize_detail": "プロジェクトやフォルダーでテストケースを整理できます。モダンなUIフレームワークによりそれらを高速に表示します。",
"usability_title": "ユーザビリティ",
"usability_detail": "定義したテストケースはテストランで何度も繰り返し使用可能です。テストランやプロジェクトのステータスをグラフで確認できます。",
"universal_title": "ユニバーサル",
"universal_detail": "多言語対応やダークテーマ機能により誰もが不自由なく使うことができます。",
"organize_test_cases": "テストケースを整理とグラフィカルなテスト管理",
"self_host": "アプリのセルフホスト",
"run_as_docker": "Docker containerによる実行",
"run_by_manually": "手動での実行"
}, },
"Header": { "Header": {
"title": "オープンソーステストケース管理ツール", "title": "オープンソーステストケース管理ツール",

View File

@@ -0,0 +1,61 @@
import { title, subtitle } from "@/components/primitives";
import { Card, CardHeader, CardBody, Avatar } from "@nextui-org/react";
import { Scale, Folder, Check, Globe } from "lucide-react";
import { useTranslations } from "next-intl";
export default function MainTitle() {
const t = useTranslations("Index");
const features = [
{
title: t("oss_title"),
detail: t("oss_detail"),
icon: <Scale size={24} color="#52e280" />,
},
{
title: t("organize_title"),
detail: t("organize_detail"),
icon: <Folder size={24} color="#52e280" />,
},
{
title: t("usability_title"),
detail: t("usability_detail"),
icon: <Check size={24} color="#52e280" />,
},
{
title: t("universal_title"),
detail: t("universal_detail"),
icon: <Globe size={24} color="#52e280" />,
},
];
return (
<>
{features.map((feature, index) => (
<Card
key={feature.title}
className={`max-w-[300px] min-h-[180px] ${
index !== 0 ? "mt-4 sm:mt-0 sm:ml-4" : ""
}`}
>
<CardHeader className="flex gap-3">
<div>
<Avatar
className="bg-green-100"
showFallback
src=""
fallback={feature.icon}
/>
</div>
<div className="flex flex-col">
<h4 className="font-bold text-large">{feature.title}</h4>
</div>
</CardHeader>
<CardBody className="pt-0">
<p className="text-default-500">{feature.detail}</p>
</CardBody>
</Card>
))}
</>
);
}

View File

@@ -41,7 +41,12 @@ export default function MainTitle({ locale }: Props) {
</Link> </Link>
</Button> </Button>
<Button color="primary" radius="full" className="ms-3"> <Button
color="primary"
radius="full"
variant="bordered"
className="ms-3"
>
<Link href={`/projects/`} locale={locale}> <Link href={`/projects/`} locale={locale}>
GitHub GitHub
</Link> </Link>
@@ -50,7 +55,7 @@ export default function MainTitle({ locale }: Props) {
href="https://github.com/kimatata/TestCaseManager" href="https://github.com/kimatata/TestCaseManager"
aria-label="Github" aria-label="Github"
showAnchorIcon showAnchorIcon
anchorIcon={<ExternalLink size={16} color="#fff" />} anchorIcon={<ExternalLink size={16} />}
></NextUiLink> ></NextUiLink>
</Button> </Button>
</div> </div>

View File

@@ -0,0 +1,44 @@
import { Code, Card, CardBody } from "@nextui-org/react";
import { useTranslations } from "next-intl";
export default function SelfHostProcedure() {
const t = useTranslations("Index");
const manualProcedures = [
{
uid: "clone",
detail: "",
code: "git clone git@github.com:kimatata/TestCaseManager.git",
},
{ uid: "go-to-backend", detail: "", code: "cd backend" },
{ uid: "backend-install", detail: "", code: "npm install" },
{ uid: "backend-start", detail: "", code: "node index" },
{ uid: "go-to-frontend", detail: "", code: "cd frontend" },
{ uid: "front-install", detail: "", code: "npm install" },
{ uid: "front-start", detail: "", code: "npm run start" },
];
return (
<>
<div>
<h3 className="text-2xl font-bold">{t("run_as_docker")}</h3>
<Card fullWidth={true} className="bg-red-400">
<CardBody>To be implemented</CardBody>
</Card>
</div>
<div className="mt-3">
<h3 className="text-2xl font-bold">{t("run_by_manually")}</h3>
<div className="mt-3">
{manualProcedures.map((procedure, index) => (
<div key={procedure.uid} className={`${index !== 0 ? "mt-3" : ""}`}>
<p>{procedure.detail}</p>
<Code radius="sm" className="min-w-96">
{procedure.code}
</Code>
</div>
))}
</div>
</div>
</>
);
}

View File

@@ -1,14 +1,17 @@
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { title } from "@/components/primitives"; import { title, subtitle } from "@/components/primitives";
import { Divider } from "@nextui-org/react";
import Image from "next/image"; import Image from "next/image";
import heroImage from "./hero.png"; import heroImage from "./hero.png";
import MainTitle from "./MainTitle"; import MainTitle from "./MainTitle";
import MainFeatures from "./MainFeatures";
import SelfHostProcedure from "./SelfHostProcedure";
export default function Home(params: { locale: string }) { export default function Home(params: { locale: string }) {
const t = useTranslations("Index"); const t = useTranslations("Index");
return ( return (
<section className="mx-auto max-w-screen-lg my-12"> <section className="mx-auto max-w-screen-xl my-12">
<div className="flex flex-wrap"> <div className="flex flex-wrap">
<div className="w-full md:w-7/12 order-last md:order-first p-4"> <div className="w-full md:w-7/12 order-last md:order-first p-4">
<MainTitle locale={params.locale} /> <MainTitle locale={params.locale} />
@@ -48,23 +51,34 @@ export default function Home(params: { locale: string }) {
</div> </div>
<div <div
className="flex flex-wrap" className="flex flex-wrap flex-col items-center sm:flex-row sm:items-start"
style={{ style={{
marginTop: "10rem", marginTop: "6rem",
}} }}
> >
<h2 className={title()}>{t("features")}</h2> <MainFeatures />
</div> </div>
<div <Divider className="my-12" />
className="flex flex-wrap"
style={{ <div className="flex flex-wrap mt-12">
marginTop: "10rem", <div className="w-full md:w-4/12 order-last md:order-first p-4">
}} <h2 className={title({ size: "sm" })}>{t("organize_test_cases")}</h2>
> </div>
<h2 className={title()}>{t("demo_screen")}</h2> <div className="w-full md:w-8/12 p-4">
<div className="mt-12"> <Image src={heroImage} alt="Hero" className="max-w-2xl" />
<Image src={heroImage} alt="Hero" /> </div>
</div>
<Divider className="my-12" />
<div className="flex flex-wrap mt-12">
<div className="w-full md:w-4/12 order-last md:order-first p-4">
<h2 className={title({ size: "sm" })}>{t("self_host")}</h2>
</div>
<div className="w-full md:w-8/12 p-4">
<SelfHostProcedure />
</div> </div>
</div> </div>
</section> </section>