(url, { method, body: JSON.stringify(playerForm) });
+
+ if (pitchingForm.appearanceId && !pitchingForm.gameDate && !pitchingForm.pitchCount) {
+ await fetchJson(`/api/pitching-appearances/${pitchingForm.appearanceId}`, { method: "DELETE" });
+ } else if (pitchingForm.gameDate && pitchingForm.pitchCount) {
+ const payload = {
+ playerId: savedPlayer._id,
+ gameDate: pitchingForm.gameDate,
+ pitchCount: pitchingForm.pitchCount,
+ notes: pitchingForm.notes ?? ""
+ };
+
+ if (pitchingForm.appearanceId) {
+ await fetchJson(`/api/pitching-appearances/${pitchingForm.appearanceId}`, {
+ method: "PATCH",
+ body: JSON.stringify(payload)
+ });
+ } else {
+ await fetchJson("/api/pitching-appearances", {
+ method: "POST",
+ body: JSON.stringify(payload)
+ });
+ }
+ }
+
setMessage(editingPlayerId ? "Player updated." : "Player added.");
setEditingPlayerId(null);
+ setShowPlayerForm(false);
setPlayerForm(emptyPlayerForm());
await loadPlayers();
} catch (submitError) {
@@ -157,6 +225,7 @@ export function RosterClient() {
| Player |
Pos |
B/T |
+ Stats |
Pitching |
Status |
Actions |
@@ -183,6 +252,20 @@ export function RosterClient() {
{player.tertiaryPosition ? {player.tertiaryPosition}
: null}
{player.batsThrows} |
+
+ {player.stats && Object.values(player.stats).some((value) => value !== null && value !== undefined) ? (
+
+ {statColumns.map(([label, key]) => (
+
+ {label}{" "}
+ {player.stats?.[key] ?? 0}
+
+ ))}
+
+ ) : (
+ No stats
+ )}
+ |
{player.pitcherAvailability.lastPitchedDate
? `${player.pitcherAvailability.lastPitchCount} on ${player.pitcherAvailability.lastPitchedDate}`
@@ -233,14 +316,62 @@ export function RosterClient() {
) : null}
- void submitPlayer()}
- submitLabel={editingPlayerId ? "Save Changes" : "Add Player"}
- />
-
-
+ void submitPlayer()}
+ submitLabel={editingPlayerId ? "Save Changes" : "Add Player"}
+ />
+
+
+ Latest Pitching Appearance
+
+ Optional. Leave blank if the player has no recent outing to track.
+
+
+
+
+
+
+
+
) : null}
);
diff --git a/baseball/src/lib/types.ts b/baseball/src/lib/types.ts
index 97be15a..b1633b8 100644
--- a/baseball/src/lib/types.ts
+++ b/baseball/src/lib/types.ts
@@ -28,6 +28,13 @@ export interface PlayerStatsInput {
stolenBases?: number | null;
}
+export interface PlayerPitchingInput {
+ appearanceId?: string | null;
+ gameDate?: string | null;
+ pitchCount?: number | null;
+ notes?: string;
+}
+
export interface GamePlayerStatsInput {
playerId: string;
playerName: string;
@@ -41,6 +48,7 @@ export interface GamePlayerStatsInput {
walks?: number | null;
strikeouts?: number | null;
stolenBases?: number | null;
+ pitchCount?: number | null;
}
export interface PitchingRuleInput {
@@ -67,6 +75,7 @@ export interface PlayerRecord extends PlayerInput {
createdAt?: string;
updatedAt?: string;
pitcherAvailability: PlayerAvailabilitySummary;
+ latestPitching?: PlayerPitchingInput | null;
}
export interface PitchingAppearanceInput {
diff --git a/baseball/src/lib/validators.ts b/baseball/src/lib/validators.ts
index f57c6da..1253863 100644
--- a/baseball/src/lib/validators.ts
+++ b/baseball/src/lib/validators.ts
@@ -90,7 +90,8 @@ export const saveGameSchema = z.object({
runsBattedIn: optionalStat,
walks: optionalStat,
strikeouts: optionalStat,
- stolenBases: optionalStat
+ stolenBases: optionalStat,
+ pitchCount: optionalStat
})
)
});
diff --git a/baseball/src/models/Game.ts b/baseball/src/models/Game.ts
index a726181..86c85c6 100644
--- a/baseball/src/models/Game.ts
+++ b/baseball/src/models/Game.ts
@@ -54,7 +54,8 @@ const gameSchema = new Schema(
runsBattedIn: { type: Number, default: null },
walks: { type: Number, default: null },
strikeouts: { type: Number, default: null },
- stolenBases: { type: Number, default: null }
+ stolenBases: { type: Number, default: null },
+ pitchCount: { type: Number, default: null }
}
]
},
diff --git a/baseball/src/models/PitchingAppearance.ts b/baseball/src/models/PitchingAppearance.ts
index c4c5409..375ea3a 100644
--- a/baseball/src/models/PitchingAppearance.ts
+++ b/baseball/src/models/PitchingAppearance.ts
@@ -2,6 +2,7 @@ import { Model, Schema, Types, model, models } from "mongoose";
export interface PitchingAppearanceDocument {
playerId: Types.ObjectId;
+ gameId?: Types.ObjectId | null;
gameDate: Date;
pitchCount: number;
notes?: string;
@@ -12,6 +13,7 @@ export interface PitchingAppearanceDocument {
const pitchingAppearanceSchema = new Schema(
{
playerId: { type: Schema.Types.ObjectId, ref: "Player", required: true, index: true },
+ gameId: { type: Schema.Types.ObjectId, ref: "Game", default: null, index: true },
gameDate: { type: Date, required: true, index: true },
pitchCount: { type: Number, required: true },
notes: { type: String, default: "" }
|