Skip to content

Commit

Permalink
Merge pull request #237 from ueckoken/main
Browse files Browse the repository at this point in the history
Release 2022-10-23 21:43:06 +0900
  • Loading branch information
hutinoatari authored Oct 23, 2022
2 parents 2d6b32d + 26bde38 commit 69f420b
Show file tree
Hide file tree
Showing 19 changed files with 724 additions and 599 deletions.
6 changes: 3 additions & 3 deletions client/_proto/spec/v1/userdata_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1147,11 +1147,11 @@ export declare class EditRaceRequest extends Message<EditRaceRequest> {
description?: string;

/**
* 出走表決定も着順確定も同じフィールドを使うけどとりあえずは運用でカバーします
* 馬のidの配列で指定
*
* @generated from field: repeated spec.v1.RaceDetail.Member members = 6;
* @generated from field: repeated uint32 members = 6;
*/
members: RaceDetail_Member[];
members: number[];

/**
* admin JWT
Expand Down
2 changes: 1 addition & 1 deletion client/_proto/spec/v1/userdata_pb.js
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ export const EditRaceRequest = proto3.makeMessageType(
{ no: 3, name: "order", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true },
{ no: 4, name: "start", kind: "message", T: Timestamp, opt: true },
{ no: 5, name: "description", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 6, name: "members", kind: "message", T: RaceDetail_Member, repeated: true },
{ no: 6, name: "members", kind: "scalar", T: 13 /* ScalarType.UINT32 */, repeated: true },
{ no: 7, name: "admin_jwt", kind: "message", T: JWT },
],
);
Expand Down
4 changes: 2 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"devDependencies": {
"@bufbuild/protoc-gen-connect-web": "0.2.1",
"@bufbuild/protoc-gen-es": "0.1.1",
"eslint": "8.25.0",
"eslint": "8.26.0",
"eslint-config-next": "12.3.1"
},
"dependencies": {
Expand All @@ -18,7 +18,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"sass": "1.55.0",
"sharp": "^0.31.1",
"sharp": "0.31.1",
"typescript": "4.8.4"
},
"scripts": {
Expand Down
355 changes: 355 additions & 0 deletions client/src/components/RegisterField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
import { FC, useState } from "react";
import { createPromiseClient } from "@bufbuild/connect-web";
import { Timestamp } from "@bufbuild/protobuf";
import {
HorseDataService,
RaceDataService,
} from "../../_proto/spec/v1/userdata_connectweb";
import { HorseDetail_Image, JWT } from "../../_proto/spec/v1/userdata_pb";
import { transport } from "../util/use-client";
import { stringToImageType } from "../util/util";

const horseClient = createPromiseClient(HorseDataService, transport);
const raceClient = createPromiseClient(RaceDataService, transport);

const RegisterRaceField: FC<{ jwt: JWT | null }> = ({ jwt }) => {
const [name, setName] = useState<string>("");
const [order, setOrder] = useState<number>(0);
const [date, setDate] = useState<string>("");
const [time, setTime] = useState<string>("");
const [description, setDescription] = useState<string>("");
return (
<fieldset>
<legend>レース登録</legend>
<div>
<label>
名前:{" "}
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
</div>
<div>
<label>
順番:{" "}
<input
type="number"
value={order}
onChange={(e) => setOrder(+e.target.value)}
/>
</label>
</div>
<div>
<label>
日付:{" "}
<input
type="date"
value={date}
onChange={(e) => setDate(e.target.value)}
/>
</label>
</div>
<div>
<label>
時刻:{" "}
<input
type="time"
value={time}
onChange={(e) => setTime(e.target.value)}
/>
</label>
</div>
<div>
<label>
説明:{" "}
<input
type="text"
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
</label>
</div>
<button
onClick={() => {
if (date === "" || time === "") {
alert("不正な入力です。");
return;
}
raceClient
.registerRace({
name,
order,
start: Timestamp.fromDate(
new Date(`${date}T${time}`)
),
adminJwt: jwt!,
})
.then(() => alert("登録完了!"))
.catch((err) => {
console.error(err);
alert("登録失敗......");
});
}}
>
登録
</button>
</fieldset>
);
};

const EditRaceField: FC<{ jwt: JWT | null }> = ({ jwt }) => {
const [id, setId] = useState<number>(0);
const [name, setName] = useState<string>("");
const [order, setOrder] = useState<number>(0);
const [date, setDate] = useState<string>("");
const [time, setTime] = useState<string>("");
const [member, setMember] = useState<string>("");
const [description, setDescription] = useState<string>("");
return (
<fieldset>
<legend>レース編集</legend>
<div>
<label>
id:{" "}
<input
type="number"
value={id}
onChange={(e) => setId(+e.target.value)}
/>
</label>
</div>
<div>
<label>
レース名:{" "}
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
</div>
<div>
<label>
R:{" "}
<input
type="number"
value={order}
onChange={(e) => setOrder(+e.target.value)}
/>
</label>
</div>
<div>
<label>
日付:{" "}
<input
type="date"
value={date}
onChange={(e) => setDate(e.target.value)}
/>
</label>
</div>
<div>
<label>
時刻:{" "}
<input
type="time"
value={time}
onChange={(e) => setTime(e.target.value)}
/>
</label>
</div>
<div>
<label>
メンバー:{" "}
<input
type="text"
value={member}
onChange={(e) => setMember(e.target.value)}
/>
</label>
</div>
<div>
<label>
説明:{" "}
<input
type="text"
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
</label>
</div>
<button
onClick={() =>
raceClient
.editRace({
adminJwt: jwt!,
id,
name: name !== "" ? name : undefined,
order: order !== 0 ? order : undefined,
start:
date !== "" && time !== ""
? Timestamp.fromDate(
new Date(`${date}T${time}`)
)
: undefined,
description:
description !== "" ? description : undefined,
members:
member !== ""
? member.split(",").map((e) => {
if (Number.isNaN(+e))
throw new Error();
return +e;
})
: undefined,
})
.then(() => alert("編集完了!"))
.catch((err) => {
console.error(err);
alert("編集失敗......");
})
}
>
編集
</button>
</fieldset>
);
};

const RegisterHorseField: FC<{ jwt: JWT | null }> = ({ jwt }) => {
const [name, setName] = useState<string>("");
const [owner, setOwner] = useState<string>("");
return (
<fieldset>
<legend>競争馬登録</legend>
<div>
<label>
馬名:{" "}
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
</div>
<div>
<label>
馬主名:{" "}
<input
type="text"
value={owner}
onChange={(e) => setOwner(e.target.value)}
/>
</label>
</div>
<button
onClick={() =>
horseClient
.registerHorse({
adminJwt: jwt!,
name,
owner,
})
.then(() => alert("登録完了!"))
.catch((err) => {
console.error(err);
alert("登録失敗......");
})
}
>
登録
</button>
</fieldset>
);
};

const EditHorseField: FC<{ jwt: JWT | null }> = ({ jwt }) => {
const [id, setId] = useState<number>(0);
const [name, setName] = useState<string>("");
const [owner, setOwner] = useState<string>("");
const [image, setImage] = useState<HorseDetail_Image | undefined>(
undefined
);
return (
<fieldset>
<legend>競争馬編集</legend>
<div>
<label>
id:{" "}
<input
type="number"
value={id}
onChange={(e) => setId(+e.target.value)}
/>
</label>
</div>
<div>
<label>
馬名:{" "}
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
</div>
<div>
<label>
馬主名:{" "}
<input
type="text"
value={owner}
onChange={(e) => setOwner(e.target.value)}
/>
</label>
</div>
<div>
<label>
写真:{" "}
<input
type="file"
onChange={(e) => {
const file = e.target.files![0];
const reader = new FileReader();
reader.onload = (ev) => {
const base64 = ev.target!.result! as string;
const regex = /^data:image\/(.+);base64,(.+)/;
const match = base64.match(regex);
if (!match) return;
const [, type, data] = match;
const img = new HorseDetail_Image();
img.type = stringToImageType(type);
img.data = new TextEncoder().encode(data);
setImage(img);
};
reader.readAsDataURL(file);
}}
/>
</label>
</div>
<button
onClick={() =>
horseClient
.editHorse({
id,
adminJwt: jwt!,
name: name !== "" ? name : undefined,
owner: owner !== "" ? owner : undefined,
image,
})
.then(() => alert("編集完了!"))
.catch((err) => {
console.error(err);
alert("編集失敗......");
})
}
>
編集
</button>
</fieldset>
);
};

export { RegisterRaceField, EditRaceField, RegisterHorseField, EditHorseField };
Loading

0 comments on commit 69f420b

Please sign in to comment.