From d4f4a539f5cd98179c617c6a10c9bd0b19b017ff Mon Sep 17 00:00:00 2001 From: Dean Wenstrand Date: Tue, 9 Jun 2026 14:44:33 -0700 Subject: [PATCH] Add camera-claim schema: venues, cameras, claim lifecycle New query/mutation surface for the camera-claim flow: getVenues (with per-camera availability), getActiveClaim, claimCamera, endClaim, extendClaim, plus VenueGQL / VenueCameraGQL / CameraClaimGQL / ClaimStatusEnum types. Co-Authored-By: Claude Opus 4.8 --- src/index.tsx | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/schema.gql | 47 ++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/index.tsx b/src/index.tsx index 593cf0d..78d4945 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -140,6 +140,18 @@ export type BucketSetInputGql = { feature: Scalars["String"]["input"]; }; +export type CameraClaimGql = { + __typename?: "CameraClaimGQL"; + cameraId: Scalars["Int"]["output"]; + createdAt: Scalars["DateTime"]["output"]; + endedAt?: Maybe; + expiresAt?: Maybe; + id: Scalars["Int"]["output"]; + status: ClaimStatusEnum; + userId: Scalars["Int"]["output"]; + videoId?: Maybe; +}; + export type CancellationFeedbackMetadataInput = { appVersion?: InputMaybe; gitRevision?: InputMaybe; @@ -200,6 +212,21 @@ export type ChallengeInvitation = { status: Scalars["String"]["output"]; }; +export enum ClaimStatusEnum { + Active = "ACTIVE", + CodeExpired = "CODE_EXPIRED", + CodeIssued = "CODE_ISSUED", + EndedByUser = "ENDED_BY_USER", + Expired = "EXPIRED", + Ingesting = "INGESTING", + ReleasedInactive = "RELEASED_INACTIVE", + Requested = "REQUESTED", + Scanning = "SCANNING", + ScanConfirmed = "SCAN_CONFIRMED", + StreamLost = "STREAM_LOST", + StreamUnreachable = "STREAM_UNREACHABLE", +} + export enum ClientUploadStatusEnum { UploadDisabled = "UPLOAD_DISABLED", UploadEnabled = "UPLOAD_ENABLED", @@ -2388,6 +2415,7 @@ export type Mutation = { blockContent: Scalars["Boolean"]["output"]; blockUser: Scalars["Boolean"]["output"]; cancelSubscription: UserSubscriptionStatusGql; + claimCamera: CameraClaimGql; commentOnVideo: Scalars["Boolean"]["output"]; createBucketSet: BucketSetGql; createChallenge: Challenge; @@ -2406,7 +2434,9 @@ export type Mutation = { editShot: EditShotReturn; editUploadStream: Scalars["Boolean"]["output"]; editUser: UserGql; + endClaim: CameraClaimGql; ensureStripeCustomerExists: UserGql; + extendClaim: CameraClaimGql; finalizePlayerAssignments: Array; findPrerecordTableLayout?: Maybe; followUser: UserGql; @@ -2448,6 +2478,11 @@ export type MutationBlockUserArgs = { userId: Scalars["Int"]["input"]; }; +export type MutationClaimCameraArgs = { + cameraId: Scalars["Int"]["input"]; + durationMinutes?: Scalars["Int"]["input"]; +}; + export type MutationCommentOnVideoArgs = { message: Scalars["String"]["input"]; parentCommentId?: InputMaybe; @@ -2531,6 +2566,15 @@ export type MutationEditUserArgs = { input: EditUserInputGql; }; +export type MutationEndClaimArgs = { + claimId: Scalars["Int"]["input"]; +}; + +export type MutationExtendClaimArgs = { + additionalMinutes?: Scalars["Int"]["input"]; + claimId: Scalars["Int"]["input"]; +}; + export type MutationFinalizePlayerAssignmentsArgs = { input: FinalizePlayerAssignmentsInput; }; @@ -2813,6 +2857,7 @@ export type Query = { challengeLeaderboard: Array; challenges: Array; doesUsernameExist: Scalars["Boolean"]["output"]; + getActiveClaim?: Maybe; getAggregatedShotMetrics: Array; getAvailableSubscriptionOptions: StripeSubscriptionOptionsGql; getBucketSet?: Maybe; @@ -2839,6 +2884,7 @@ export type Query = { getUserVideos: VideoHistoryGql; getUsernames: Array; getUsersMatching: Array; + getVenues: Array; getVideo: VideoGql; getVideoMakePercentageIntervals: Array; getVideos: Array; @@ -3542,6 +3588,24 @@ export type UserSubscriptionStatusGql = { validUntil?: Maybe; }; +export type VenueCameraGql = { + __typename?: "VenueCameraGQL"; + enabled: Scalars["Boolean"]["output"]; + id: Scalars["Int"]["output"]; + isAvailable: Scalars["Boolean"]["output"]; + tableLabel: Scalars["String"]["output"]; + venueId: Scalars["Int"]["output"]; +}; + +export type VenueGql = { + __typename?: "VenueGQL"; + cameras: Array; + id: Scalars["Int"]["output"]; + latitude?: Maybe; + longitude?: Maybe; + name: Scalars["String"]["output"]; +}; + export type VideoFeedInputGql = | { allUsers: Scalars["Boolean"]["input"]; diff --git a/src/schema.gql b/src/schema.gql index 4c6dc1c..ef8fdf1 100644 --- a/src/schema.gql +++ b/src/schema.gql @@ -11,6 +11,8 @@ type Query { myChallengeInvitations: [ChallengeInvitation!]! ruleSets: [RuleSet!]! myChallengeEntries: [ChallengeEntry!]! + getVenues: [VenueGQL!]! + getActiveClaim: CameraClaimGQL getDeployedConfig: DeployedConfigGQL! waitFor(duration: Float!): Float! getFeedVideos( @@ -681,6 +683,48 @@ type PlayerSummaryGQL { averageTimeBetweenShots: Float } +type VenueGQL { + id: Int! + name: String! + latitude: Float + longitude: Float + cameras: [VenueCameraGQL!]! +} + +type VenueCameraGQL { + id: Int! + venueId: Int! + tableLabel: String! + enabled: Boolean! + isAvailable: Boolean! +} + +type CameraClaimGQL { + id: Int! + cameraId: Int! + userId: Int! + videoId: Int + status: ClaimStatusEnum! + expiresAt: DateTime + endedAt: DateTime + createdAt: DateTime! +} + +enum ClaimStatusEnum { + REQUESTED + CODE_ISSUED + SCANNING + SCAN_CONFIRMED + INGESTING + ACTIVE + ENDED_BY_USER + EXPIRED + STREAM_LOST + STREAM_UNREACHABLE + CODE_EXPIRED + RELEASED_INACTIVE +} + type DeployedConfigGQL { allowNewUsers: Boolean! firebase: Boolean! @@ -1129,6 +1173,9 @@ type Mutation { submitChallengeEntry(entryId: ID!, videoId: ID!): ChallengeEntry! dismissChallenge(challengeId: ID!): Boolean! undismissChallenge(challengeId: ID!): Boolean! + claimCamera(cameraId: Int!, durationMinutes: Int! = 60): CameraClaimGQL! + endClaim(claimId: Int!): CameraClaimGQL! + extendClaim(claimId: Int!, additionalMinutes: Int! = 60): CameraClaimGQL! setLoggerLevel(path: String!, level: String!): Boolean! reactToVideo(videoId: Int!, reaction: ReactionEnum): Boolean! commentOnVideo(