Skip to content

Commit

Permalink
add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
toririm committed Oct 2, 2024
1 parent 5e2aad6 commit 31df9bc
Show file tree
Hide file tree
Showing 22 changed files with 129 additions and 5 deletions.
5 changes: 5 additions & 0 deletions app/components/functional/useFocusRef.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { useEffect, useRef } from "react";

/**
* focus が true に変化した際に ref が指す DOM にフォーカスを当てる
* @param focus フォーカスを当てるかどうか
* @returns
*/
const useFocusRef = (focus: boolean) => {
const DOMRef = useRef<HTMLInputElement>(null);

Expand Down
4 changes: 4 additions & 0 deletions app/components/functional/useInputStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const InputStatusList = [
"submit",
] as const;

/**
* CashierV2 のドメイン固有のフック
* 入力ステータスを管理する
*/
const useInputStatus = () => {
const [inputStatus, setInputStatus] =
useState<(typeof InputStatusList)[number]>("discount");
Expand Down
5 changes: 5 additions & 0 deletions app/components/functional/useLatestOrderId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { useMemo } from "react";
import type { WithId } from "~/lib/typeguard";
import type { OrderEntity } from "~/models/order";

/**
* オーダーのIDの最大値と次のIDを取得する
* @param orders オーダーのリスト
* @returns オーダーIDの最大値と次のID
*/
const useLatestOrderId = (orders: WithId<OrderEntity>[] | undefined) => {
const latestOrderId = useMemo(
() => orders?.reduce((acc, cur) => Math.max(acc, cur.orderId), 0) ?? 0,
Expand Down
13 changes: 13 additions & 0 deletions app/components/functional/useOrderState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ const reducer: OrderReducer<OrderAction> = (state, action): OrderEntity => {
}
};

/**
* オーダーの状態を管理する
* reducer が受け付ける状態には下記がある:
* - clear
* - applyDiscount
* - removeDiscount
* - addItem
* - mutateItem
* - setReceived
* - setDescription
* - updateOrderId
* @returns オーダーの状態とそれを更新する関数
*/
const useOrderState = () =>
useReducer(reducer, OrderEntity.createNew({ orderId: -1 }));

Expand Down
5 changes: 5 additions & 0 deletions app/components/functional/useUISession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ type UISession = {
key: string;
};

/**
* UI のセッションを管理するためのフック
* renewUISession を呼ぶことでセッションを更新できる
* UISession.key を DOM の key に指定することで、セッションが変更されたときに再描画される
*/
const useUISession = (): [UISession, () => void] => {
const [date, setDate] = useState(new Date());

Expand Down
4 changes: 3 additions & 1 deletion app/components/molecules/AttractiveTextBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ type props = InputProps & {
focus: boolean;
};

// focus が true のときにフォーカスを当てるテキストボックス
/**
* focus が true のときに自動でフォーカスを当てるテキストボックス
*/
const AttractiveTextBox = ({ focus, onTextSet, ...props }: props) => {
const [text, setText] = useState("");
const DOMRef = useFocusRef(focus);
Expand Down
3 changes: 3 additions & 0 deletions app/components/molecules/InputNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { AttractiveTextBox } from "./AttractiveTextBox";

type props = ComponentPropsWithRef<typeof AttractiveTextBox>;

/**
* 上下キーで数値を増減させない数値専用のテキストボックス
*/
const InputNumber = ({ ...props }: props) => {
useEffect(() => {
const handler = (event: KeyboardEvent) => {
Expand Down
4 changes: 3 additions & 1 deletion app/components/molecules/ThreeDigitsInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
} from "react";
import { InputOTP, InputOTPGroup, InputOTPSlot } from "../ui/input-otp";

// 3桁の数字を入力するためのコンポーネント
/**
* 3桁の数字を入力するためのコンポーネント
*/
const ThreeDigitsInput = forwardRef<
ElementRef<typeof InputOTP>,
Omit<
Expand Down
5 changes: 5 additions & 0 deletions app/components/organisms/ChargeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ type props = {
order: OrderEntity;
};

/**
* おつりの表示をするコンポーネント
* @param props
* @returns
*/
const ChargeView = ({ order }: props) => {
const chargeView: string | number = useMemo(() => {
const charge = order.getCharge();
Expand Down
4 changes: 3 additions & 1 deletion app/components/organisms/DiscountInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ type props = ComponentPropsWithoutRef<typeof ThreeDigitsInput> & {
onDiscountOrderRemoved: () => void;
};

// 割引券番号を入力するためのコンポーネント
/**
* 割引券番号を入力するためのコンポーネント
*/
const DiscountInput = ({
focus,
orders,
Expand Down
3 changes: 3 additions & 0 deletions app/components/organisms/ItemAssign.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ type props = {
focus: boolean;
};

/**
* Enterでアサイン入力欄を開けて、アイテムのアサインを変更できるコンポーネント
*/
const ItemAssign = ({ item, idx, mutateItem, focus }: props) => {
const [editable, setEditable] = useState(false);
const [assignee, setAssinee] = useState<string | null>(null);
Expand Down
5 changes: 4 additions & 1 deletion app/components/organisms/OrderAlertDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
AlertDialogTitle,
} from "../ui/alert-dialog";

// 確定前にオーダーの内容を表示するダイアログ
// TODO: 表示内容が整ってないので、きれいにする
/**
* 確定前にオーダーの内容を表示するダイアログ
*/
const OrderAlertDialog = forwardRef<
null,
ComponentPropsWithoutRef<typeof AlertDialog> & {
Expand Down
4 changes: 3 additions & 1 deletion app/components/organisms/OrderItemEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ type props = {
discountOrder: boolean;
};

// オーダーのアイテムや割引情報を表示するコンポーネント
/**
* オーダーのアイテムや割引情報を表示するコンポーネント
*/
const OrderItemEdit = ({
focus,
discountOrder,
Expand Down
5 changes: 5 additions & 0 deletions app/components/pages/CashierV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ type props = {
submitPayload: (order: OrderEntity) => void;
};

/**
* キャッシャー画面のコンポーネント
*
* データの入出力は親コンポーネントに任せる
*/
const CashierV2 = ({ items, orders, submitPayload }: props) => {
const [newOrder, newOrderDispatch] = useOrderState();
const { inputStatus, proceedStatus, previousStatus, setInputStatus } =
Expand Down
6 changes: 6 additions & 0 deletions app/firebase/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ const parseDateProperty = (data: DocumentData): DocumentData => {
return recursivelyParsedData;
};

/**
* Firestore のデータを ItemEntity に変換する
*/
export const itemConverter: FirestoreDataConverter<WithId<ItemEntity>> = {
toFirestore: converter(itemSchema).toFirestore,
fromFirestore: (
Expand All @@ -73,6 +76,9 @@ export const itemConverter: FirestoreDataConverter<WithId<ItemEntity>> = {
},
};

/**
* Firestore のデータを OrderEntity に変換する
*/
export const orderConverter: FirestoreDataConverter<WithId<OrderEntity>> = {
toFirestore: converter(orderSchema).toFirestore,
fromFirestore: (
Expand Down
3 changes: 3 additions & 0 deletions app/firebase/subscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
import type { SWRSubscription } from "swr/subscription";
import { prodDB } from "./firestore";

/**
* Firestore のコレクションを監視する SWRSubscription を生成する
*/
export const collectionSub = <T>(
{ converter }: { converter: FirestoreDataConverter<T> },
...queryConstraints: QueryConstraint[]
Expand Down
3 changes: 3 additions & 0 deletions app/lib/custom-loader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { type ClientLoaderFunction, useLoaderData } from "@remix-run/react";

/**
* clientLoader のデータを JSON にシリアライズせずに直接取得する関数
*/
export const useClientLoaderData = <T extends ClientLoaderFunction>() =>
useLoaderData<T>() as Awaited<ReturnType<T>>;
15 changes: 15 additions & 0 deletions app/lib/typeguard.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
/**
* オブジェクトに id プロパティを持っていることを保証するユーティリティ型
*/
export type WithId<T extends { id?: unknown }> = T &
Record<"id", NonNullable<T["id"]>>;

/**
* オブジェクトが id プロパティを持っているかどうかを判定する
* TypeGuard として使用する
*
* @param obj 判定するオブジェクト
* @returns obj が id プロパティを持っている場合は true
* @example
* const obj = { id: 1, name: "name" };
* if (hasId(obj)) {
* console.log(obj.id);
* }
*/
export const hasId = <T extends { id?: unknown }>(obj: T): obj is WithId<T> => {
return obj.id !== undefined && obj.id !== null;
};
4 changes: 4 additions & 0 deletions app/lib/webhook.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* Slackにメッセージを送信する
* @param message 送信するメッセージ
*/
export const sendSlackMessage = async (message: string) => {
const webhookUrl = import.meta.env.VITE_WEBHOOK_URL;

Expand Down
32 changes: 32 additions & 0 deletions app/models/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,41 +169,69 @@ export class OrderEntity implements Order {
// methods
// --------------------------------------------------

/**
* コーヒーの数を取得する
* @returns 割引の対象となるコーヒーの数
*/
getCoffeeCount() {
// milk 以外のアイテムの数を返す
// TODO(toririm): このメソッドは items が変更された時だけでいい
return this.items.filter((item) => item.type !== "milk").length;
}

/**
* オーダーを準備完了状態に変更する
*/
beReady() {
// orderReady は false -> true にしか変更できないようにする
this._orderReady = true;
}

/**
* オーダーを提供済み状態に変更する
*/
beServed() {
// servedAt は null -> Date にしか変更できないようにする
this._servedAt = new Date();
}

/**
* 割引を適用する
* @param previousOrder 割引の参照となる前回のオーダー
*/
applyDiscount(previousOrder: OrderEntity) {
this._discountOrderId = previousOrder.orderId;
this._discountOrderCups = previousOrder.getCoffeeCount();
}

/**
* 割引を解除する
*/
removeDiscount() {
this._discountOrderId = null;
this._discountOrderCups = 0;
}

/**
* オーダーを作成した時刻を更新する
*/
nowCreated() {
// createdAt を更新
this._createdAt = new Date();
}

/**
* お釣りを計算する
* @returns お釣り
*/
getCharge() {
return this.received - this.billingAmount;
}

/**
* メソッドを持たない Order オブジェクトに変換する
* @returns Order オブジェクト
*/
toOrder(): Order {
return {
id: this.id,
Expand All @@ -223,6 +251,10 @@ export class OrderEntity implements Order {
};
}

/**
* オーダーを複製する
* ただし、items は参照を共有することに注意
*/
clone(): WithId<OrderEntity>;
clone(): OrderEntity;
clone(): WithId<OrderEntity> | OrderEntity {
Expand Down
1 change: 1 addition & 0 deletions app/routes/cashier-v2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { stringToJSONSchema } from "~/lib/custom-zod";
import { OrderEntity, orderSchema } from "~/models/order";
import { orderRepository } from "~/repositories/order";

// コンポーネントではデータの取得と更新のみを行う
export default function Cashier() {
const { data: items } = useSWRSubscription(
"items",
Expand Down
1 change: 1 addition & 0 deletions app/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
}
}

/* input要素でtype="number"のものについては、数値の上下を変更するボタンを非表示にする */
@layer base {
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button,
Expand Down

0 comments on commit 31df9bc

Please sign in to comment.