diff --git a/.github/workflows/sync-develop.yml b/.github/workflows/sync-develop.yml new file mode 100644 index 0000000..e8c0a86 --- /dev/null +++ b/.github/workflows/sync-develop.yml @@ -0,0 +1,24 @@ +name: Sync develop with main + +on: + push: + branches: + - main + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Merge main into develop + run: | + git config user.name "TrackGeekBot" + git config user.email "256638171+TrackGeekBot@users.noreply.github.com" + git checkout develop + git merge origin/main --no-ff -m "chore: sync develop with main" + git push origin develop + env: + GITHUB_TOKEN: ${{ secrets.GHT }} \ No newline at end of file diff --git a/src/components/pages/user/reviews-tab.tsx b/src/components/pages/user/reviews-tab.tsx index 7fbd24c..4225ba5 100644 --- a/src/components/pages/user/reviews-tab.tsx +++ b/src/components/pages/user/reviews-tab.tsx @@ -143,7 +143,7 @@ export function UserReviewsTab({ coverURL={reviewMediaImage(contentType, review)} reviewText={review.summary ?? ""} notes={review.notes} - story={review.story} + story={mediaContent.hasStory ? review.story : undefined} routeName={mediaContent.routeName} entityId={entityId} date={new Date(review.createdAt)} diff --git a/src/components/shared/modals/episodic-content.tsx b/src/components/shared/modals/episodic-content.tsx index 687e2ff..f215daa 100644 --- a/src/components/shared/modals/episodic-content.tsx +++ b/src/components/shared/modals/episodic-content.tsx @@ -502,6 +502,8 @@ export function EpisodicContentModal({ id="rewatches" type="number" min={0} + max={999} + step={1} placeholder="0" className="bg-background" {...progressForm.register("watchCount")} diff --git a/src/components/shared/modals/game.tsx b/src/components/shared/modals/game.tsx index 7b85a08..78cc03e 100644 --- a/src/components/shared/modals/game.tsx +++ b/src/components/shared/modals/game.tsx @@ -55,7 +55,7 @@ function createProgressSchema(t: TFunction) { return z.object({ status: z.string(), completion: z.string(), - progress: z.string(), + hoursPlayed: z.string(), playCount: z.string(), startDate: z.date().optional(), finishDate: z.date().optional(), @@ -85,7 +85,7 @@ interface GameProgressData { status: ProgressStatus; playCount: number | null; completion: string | null; - progress: number | null; + hoursPlayed: number | null; notes: string | null; startedAt: string | null; completedAt: string | null; @@ -129,7 +129,7 @@ export function GameModal({ gameId, onClose }: GameModalProps) { defaultValues: { status: "", completion: "", - progress: "", + hoursPlayed: "", playCount: "", startDate: undefined, finishDate: undefined, @@ -220,7 +220,7 @@ export function GameModal({ gameId, onClose }: GameModalProps) { progressForm.reset({ status: ENUM_TO_STATUS[progress.status] ?? "", completion: progress.completion ?? "", - progress: progress.progress != null ? String(progress.progress) : "", + hoursPlayed: progress.hoursPlayed != null ? String(progress.hoursPlayed) : "", playCount: progress.playCount != null ? String(progress.playCount) : "", notes: progress.notes ?? "", startDate: progress.startedAt ? new Date(progress.startedAt) : undefined, @@ -258,7 +258,7 @@ export function GameModal({ gameId, onClose }: GameModalProps) { status, playCount: data.playCount ? Number(data.playCount) : undefined, completion: data.completion || undefined, - progress: data.progress ? Number(data.progress) : undefined, + hoursPlayed: data.hoursPlayed ? Number(data.hoursPlayed) : undefined, notes: data.notes.trim() || undefined, startedAt: data.startDate ?? undefined, completedAt: status === "Completed" ? (data.finishDate ?? new Date()) : (data.finishDate ?? undefined), @@ -476,20 +476,19 @@ export function GameModal({ gameId, onClose }: GameModalProps) { - - {t("feed:progress")} + + {t("feed:hoursPlayed")} - % + h diff --git a/src/components/shared/modals/movie.tsx b/src/components/shared/modals/movie.tsx index 0a06f4f..d7d9340 100644 --- a/src/components/shared/modals/movie.tsx +++ b/src/components/shared/modals/movie.tsx @@ -58,6 +58,7 @@ type ReviewFormData = z.infer>; interface MovieProgressData { id: string; status: ProgressStatus; + watchCount: number | null; } interface MovieModalProps { @@ -73,6 +74,7 @@ export function MovieModal({ movieId, onClose }: MovieModalProps) { const enabled = !!userId && !!movieId; const [selectedStatus, setSelectedStatus] = useState(""); + const [rewatchCount, setRewatchCount] = useState(""); const [newListInput, setNewListInput] = useState(null); const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false); @@ -147,6 +149,7 @@ export function MovieModal({ movieId, onClose }: MovieModalProps) { if (!progress) return; setSelectedStatus(ENUM_TO_STATUS[progress.status] ?? ""); + setRewatchCount(progress.watchCount != null ? String(progress.watchCount) : ""); }, [progressQuery.data]); useEffect(() => { @@ -171,10 +174,11 @@ export function MovieModal({ movieId, onClose }: MovieModalProps) { }; const saveProgressMutation = useMutation({ - mutationFn: (status: string) => + mutationFn: (data: { status: string; watchCount?: number }) => api.post(apiEndpoints.movieProgress, { movieId, - status: STATUS_TO_ENUM[status], + status: STATUS_TO_ENUM[data.status], + watchCount: data.watchCount, }), onSuccess: invalidateProgress, }); @@ -263,7 +267,10 @@ export function MovieModal({ movieId, onClose }: MovieModalProps) { } try { - await saveProgressMutation.mutateAsync(selectedStatus); + await saveProgressMutation.mutateAsync({ + status: selectedStatus, + watchCount: rewatchCount ? Number(rewatchCount) : undefined, + }); const review = reviewForm.getValues(); @@ -309,6 +316,24 @@ export function MovieModal({ movieId, onClose }: MovieModalProps) { + + + + {t("feed:totalRewatches")} + + setRewatchCount(e.target.value)} + aria-label={t("feed:totalRewatches")} + /> +
diff --git a/src/hooks/game.ts b/src/hooks/game.ts index eaeca23..fec43b4 100644 --- a/src/hooks/game.ts +++ b/src/hooks/game.ts @@ -2,7 +2,7 @@ import { useMutation, useQuery } from "@tanstack/react-query"; import { api, apiEndpoints } from "@/lib/api.ts"; interface GameProgress { - progress: number; + hoursPlayed: number; status: string | null; completionStatus: string | null; replays: number; diff --git a/src/hooks/progress.ts b/src/hooks/progress.ts index 362172b..621c79f 100644 --- a/src/hooks/progress.ts +++ b/src/hooks/progress.ts @@ -2,7 +2,7 @@ import { useInfiniteQuery } from "@tanstack/react-query"; import type { FavoriteItem } from "@/components/pages/user/overview-tab/favorite-card"; import { type ApiTypes, api, apiEndpoints } from "@/lib/api.ts"; -const ITEMS_PER_PAGE = 18; +const ITEMS_PER_PAGE = 200; type ProgressStatsKey = keyof ApiTypes.User["progressStats"]; diff --git a/src/lib/i18n/locales/en-US/feed.json b/src/lib/i18n/locales/en-US/feed.json index f8861ab..f4a8cfd 100644 --- a/src/lib/i18n/locales/en-US/feed.json +++ b/src/lib/i18n/locales/en-US/feed.json @@ -91,6 +91,7 @@ }, "totalRereads": "Total Rereads", "totalReplays": "Total Replays", + "hoursPlayed": "Hours Played", "completionStatus": { "label": "Completion Status", "select": "Select a completion status",