Compare commits

..

1 Commits

Author SHA1 Message Date
Dean Wenstrand
d4f4a539f5 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 <noreply@anthropic.com>
2026-06-09 14:44:33 -07:00
2 changed files with 111 additions and 53 deletions

View File

@@ -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<Scalars["DateTime"]["output"]>;
expiresAt?: Maybe<Scalars["DateTime"]["output"]>;
id: Scalars["Int"]["output"];
status: ClaimStatusEnum;
userId: Scalars["Int"]["output"];
videoId?: Maybe<Scalars["Int"]["output"]>;
};
export type CancellationFeedbackMetadataInput = {
appVersion?: InputMaybe<Scalars["String"]["input"]>;
gitRevision?: InputMaybe<Scalars["String"]["input"]>;
@@ -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",
@@ -331,7 +358,6 @@ export type EditableShotFieldInputGql = {
export enum EntitlementSourceTypeEnum {
Admin = "ADMIN",
AlphaLegacy = "ALPHA_LEGACY",
Apple = "APPLE",
Manual = "MANUAL",
Stripe = "STRIPE",
}
@@ -2389,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;
@@ -2407,7 +2434,9 @@ export type Mutation = {
editShot: EditShotReturn;
editUploadStream: Scalars["Boolean"]["output"];
editUser: UserGql;
endClaim: CameraClaimGql;
ensureStripeCustomerExists: UserGql;
extendClaim: CameraClaimGql;
finalizePlayerAssignments: Array<PlayerClusterGql>;
findPrerecordTableLayout?: Maybe<HomographyInfoGql>;
followUser: UserGql;
@@ -2430,7 +2459,6 @@ export type Mutation = {
startChallenge: ChallengeEntry;
submitCancellationFeedback: Scalars["Boolean"]["output"];
submitChallengeEntry: ChallengeEntry;
syncAppleSubscription: SyncAppleSubscriptionResultGql;
undismissChallenge: Scalars["Boolean"]["output"];
unfollowUser: UserGql;
updateShotAnnotations: UpdateShotAnnotationReturn;
@@ -2450,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<Scalars["Int"]["input"]>;
@@ -2533,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;
};
@@ -2634,10 +2676,6 @@ export type MutationSubmitChallengeEntryArgs = {
videoId: Scalars["ID"]["input"];
};
export type MutationSyncAppleSubscriptionArgs = {
input: SyncAppleSubscriptionInputGql;
};
export type MutationUndismissChallengeArgs = {
challengeId: Scalars["ID"]["input"];
};
@@ -2819,8 +2857,8 @@ export type Query = {
challengeLeaderboard: Array<ChallengeEntry>;
challenges: Array<Challenge>;
doesUsernameExist: Scalars["Boolean"]["output"];
getActiveClaim?: Maybe<CameraClaimGql>;
getAggregatedShotMetrics: Array<AggregateResultGql>;
getAppleAppAccountToken: Scalars["String"]["output"];
getAvailableSubscriptionOptions: StripeSubscriptionOptionsGql;
getBucketSet?: Maybe<BucketSetGql>;
getDeployedConfig: DeployedConfigGql;
@@ -2846,6 +2884,7 @@ export type Query = {
getUserVideos: VideoHistoryGql;
getUsernames: Array<Scalars["String"]["output"]>;
getUsersMatching: Array<UserGql>;
getVenues: Array<VenueGql>;
getVideo: VideoGql;
getVideoMakePercentageIntervals: Array<MakePercentageIntervalGql>;
getVideos: Array<VideoGql>;
@@ -3384,27 +3423,6 @@ export type SuccessfulAddAddShotAnnotationErrors =
| AddShotAnnotationErrors
| SuccessfulAdd;
export type SyncAppleSubscriptionInputGql = {
signedRenewalInfo?: InputMaybe<Scalars["String"]["input"]>;
signedTransactionInfo: Scalars["String"]["input"];
};
export type SyncAppleSubscriptionResultGql = {
__typename?: "SyncAppleSubscriptionResultGQL";
appleStatus?: Maybe<Scalars["Int"]["output"]>;
entitlementEndsAt?: Maybe<Scalars["DateTime"]["output"]>;
entitlementSource?: Maybe<EntitlementSourceTypeEnum>;
entitlementStartsAt?: Maybe<Scalars["DateTime"]["output"]>;
errorCode?: Maybe<Scalars["String"]["output"]>;
errorMessage?: Maybe<Scalars["String"]["output"]>;
expiresAt?: Maybe<Scalars["DateTime"]["output"]>;
hasActiveSubscription: Scalars["Boolean"]["output"];
latestTransactionId?: Maybe<Scalars["String"]["output"]>;
ok: Scalars["Boolean"]["output"];
originalTransactionId?: Maybe<Scalars["String"]["output"]>;
productId?: Maybe<Scalars["String"]["output"]>;
};
export type TableStateGql = {
__typename?: "TableStateGQL";
homography?: Maybe<HomographyInfoGql>;
@@ -3570,6 +3588,24 @@ export type UserSubscriptionStatusGql = {
validUntil?: Maybe<Scalars["DateTime"]["output"]>;
};
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<VenueCameraGql>;
id: Scalars["Int"]["output"];
latitude?: Maybe<Scalars["Float"]["output"]>;
longitude?: Maybe<Scalars["Float"]["output"]>;
name: Scalars["String"]["output"];
};
export type VideoFeedInputGql =
| {
allUsers: Scalars["Boolean"]["input"];

View File

@@ -11,6 +11,8 @@ type Query {
myChallengeInvitations: [ChallengeInvitation!]!
ruleSets: [RuleSet!]!
myChallengeEntries: [ChallengeEntry!]!
getVenues: [VenueGQL!]!
getActiveClaim: CameraClaimGQL
getDeployedConfig: DeployedConfigGQL!
waitFor(duration: Float!): Float!
getFeedVideos(
@@ -98,7 +100,6 @@ type Query {
): UserRelationshipsResult!
getAvailableSubscriptionOptions: StripeSubscriptionOptionsGQL!
getUserSubscriptionStatus: UserSubscriptionStatusGQL!
getAppleAppAccountToken: String!
getQuotaStatus: QuotaStatusGQL!
getPlayTime(userId: Int!, filters: VideoFilterInput = null): UserPlayTimeGQL!
getUserVideos(
@@ -682,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!
@@ -1021,7 +1064,6 @@ enum EntitlementSourceTypeEnum {
ADMIN
MANUAL
STRIPE
APPLE
ALPHA_LEGACY
}
@@ -1131,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(
@@ -1177,9 +1222,6 @@ type Mutation {
retireTags(tagIds: [Int!]!): Boolean!
ensureStripeCustomerExists: UserGQL!
deleteUser: Boolean!
syncAppleSubscription(
input: SyncAppleSubscriptionInputGQL!
): SyncAppleSubscriptionResultGQL!
createSubscription(priceId: String!): CreateSubscriptionResultGQL!
createCustomerPortalSession: CreateCustomerPortalSessionResultGQL!
cancelSubscription: UserSubscriptionStatusGQL!
@@ -1333,26 +1375,6 @@ input EditUserInputGQL {
agreesToMarketing: Boolean = null
}
type SyncAppleSubscriptionResultGQL {
ok: Boolean!
errorCode: String
errorMessage: String
hasActiveSubscription: Boolean!
entitlementSource: EntitlementSourceTypeEnum
entitlementStartsAt: DateTime
entitlementEndsAt: DateTime
appleStatus: Int
originalTransactionId: String
latestTransactionId: String
productId: String
expiresAt: DateTime
}
input SyncAppleSubscriptionInputGQL {
signedTransactionInfo: String!
signedRenewalInfo: String = null
}
type CreateSubscriptionResultGQL {
checkoutUrl: String!
sessionId: String!