diff --git a/sysken-pay-front/src/components/features/home/ChargeButton/ChargeButton.module.scss b/sysken-pay-front/src/components/features/home/ChargeButton/ChargeButton.module.scss
new file mode 100644
index 0000000..60eb52f
--- /dev/null
+++ b/sysken-pay-front/src/components/features/home/ChargeButton/ChargeButton.module.scss
@@ -0,0 +1,25 @@
+.chargeButton {
+ margin-bottom: 1.5rem;
+ width: 90%;
+ max-width: 88rem;
+ height: 10rem;
+ background-color: $blue-40;
+ color: $white;
+ font-size: 4.0625rem;
+ font-weight: bold;
+ border: none;
+ border-radius: 1.5rem;
+ cursor: pointer;
+ box-shadow: 0 0.25rem 0.625rem $shadow-20;
+ transition: opacity 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
+
+ &:hover {
+ opacity: 0.85;
+ }
+
+ &:active {
+ transform: scale(0.97);
+ box-shadow: 0 0.125rem 0.25rem $shadow-20;
+ opacity: 0.9;
+ }
+}
diff --git a/sysken-pay-front/src/components/features/home/ChargeButton/index.tsx b/sysken-pay-front/src/components/features/home/ChargeButton/index.tsx
new file mode 100644
index 0000000..b781428
--- /dev/null
+++ b/sysken-pay-front/src/components/features/home/ChargeButton/index.tsx
@@ -0,0 +1,20 @@
+import { useNavigate } from "react-router-dom";
+import styles from "./ChargeButton.module.scss";
+
+interface ChargeButtonProps {
+ onCharge?: () => void;
+}
+
+export function ChargeButton({ onCharge }: ChargeButtonProps) {
+ const navigate = useNavigate();
+
+ return (
+
+ );
+}
diff --git a/sysken-pay-front/src/components/features/home/HomeButtons/HomeButtons.module.scss b/sysken-pay-front/src/components/features/home/HomeButtons/HomeButtons.module.scss
deleted file mode 100644
index 3725d19..0000000
--- a/sysken-pay-front/src/components/features/home/HomeButtons/HomeButtons.module.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-.checkoutButton {
- width: 90%;
- max-width: 88rem;
- height: 32rem;
- background-color: $white;
- color: $blue-40;
- font-size: 6.8rem;
- font-weight: bold;
- border: 1.25rem solid $blue-40;
- border-radius: 2.625rem;
- cursor: pointer;
- box-shadow: 0 0.25rem 0.625rem $shadow-20;
- transition: opacity 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
-
- &:hover {
- opacity: 0.85;
- }
-
- &:active {
- transform: scale(0.97);
- box-shadow: 0 0.125rem 0.25rem $shadow-20;
- opacity: 0.9;
- }
-}
-
-.chargeButton {
- width: 90%;
- max-width: 88rem;
- height: 10rem;
- background-color: $blue-40;
- color: $white;
- font-size: 4.0625rem;
- font-weight: bold;
- border: none;
- border-radius: 1.5rem;
- cursor: pointer;
- box-shadow: 0 0.25rem 0.625rem $shadow-20;
- transition: opacity 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
-
- &:hover {
- opacity: 0.85;
- }
-
- &:active {
- transform: scale(0.97);
- box-shadow: 0 0.125rem 0.25rem $shadow-20;
- opacity: 0.9;
- }
-}
diff --git a/sysken-pay-front/src/components/features/home/HomeButtons/index.tsx b/sysken-pay-front/src/components/features/home/HomeButtons/index.tsx
deleted file mode 100644
index 91e4270..0000000
--- a/sysken-pay-front/src/components/features/home/HomeButtons/index.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { useNavigate } from "react-router-dom";
-import styles from "./HomeButtons.module.scss";
-
-interface HomeButtonsProps {
- onBuy?: () => void;
- onCharge?: () => void;
-}
-
-export function HomeButtons({ onBuy, onCharge }: HomeButtonsProps) {
- const navigate = useNavigate();
-
- return (
- <>
-
-
- >
- );
-}
diff --git a/sysken-pay-front/src/pages/index.module.scss b/sysken-pay-front/src/pages/index.module.scss
index 7d41ce4..18f7988 100644
--- a/sysken-pay-front/src/pages/index.module.scss
+++ b/sysken-pay-front/src/pages/index.module.scss
@@ -11,6 +11,40 @@
flex-direction: column;
align-items: center;
justify-content: center;
- gap: 3rem;
padding: 1.5rem;
}
+
+.error {
+ position: fixed;
+ bottom: 3.5rem;
+ left: 50%;
+ transform: translateX(-50%);
+ display: flex;
+ align-items: center;
+ background-color: $red-10;
+ border: 0.125rem solid $red-100;
+ border-radius: 1rem;
+ color: $red-100;
+ font-size: 1.4rem;
+ font-weight: $bold;
+ text-align: center;
+ padding: 1.25rem 2rem;
+ margin: 0;
+ width: fit-content;
+ max-width: calc(100% - 4rem);
+ box-sizing: border-box;
+ z-index: 10;
+ animation: fadeIn 0.2s ease-out;
+ will-change: opacity, transform;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateX(-50%) translateY(-0.5rem);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(-50%) translateY(0);
+ }
+}
diff --git a/sysken-pay-front/src/pages/index.tsx b/sysken-pay-front/src/pages/index.tsx
index 2878934..28c6c05 100644
--- a/sysken-pay-front/src/pages/index.tsx
+++ b/sysken-pay-front/src/pages/index.tsx
@@ -1,14 +1,42 @@
import type { JSX } from "react";
+import { useState, useEffect } from "react";
+import { useNavigate } from "react-router-dom";
import Header from "../components/layouts/Header";
-import { HomeButtons } from "../components/features/home/HomeButtons";
+import { ChargeButton } from "../components/features/home/ChargeButton";
+import { BarcodeReader } from "../components/ui/BarcodeReader";
+import { useCartStore } from "../store/useCartStore";
+import { ItemRepositoryImpl } from "../adapter/repository/ItemRepositoryImpl";
import styles from "./index.module.scss";
export default function Home(): JSX.Element {
+ const navigate = useNavigate();
+ const addItem = useCartStore((state) => state.addItem);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ if (!error) return;
+ const timer = setTimeout(() => setError(null), 5000);
+ return () => clearTimeout(timer);
+ }, [error]);
+
+ const handleScan = async (barcode: string) => {
+ try {
+ const data = await ItemRepositoryImpl.getItemByJanCode(barcode);
+ if (!data?.item_id) throw new Error("商品が見つかりませんでした。ご不明の際は担当者にご連絡ください。");
+ addItem(data);
+ navigate("/buy/list");
+ } catch (e) {
+ setError(e instanceof Error ? e.message : "商品の取得に失敗しました");
+ }
+ };
+
return (
-
+
+ {error && {error}
}
+
);