learning_ai_common_plat/packages/react-native-platform-sdk/src/surveys/index.ts
saravanakumardb1 4ca9b73d75 fix(platform): build react-native-platform-sdk + fix admin-web typecheck errors
- react-native-platform-sdk: add tsconfig.json + 13 source files (core, auth, telemetry, feature-flags, kill-switch, broadcasts, surveys)
- react-native-platform-sdk: React hooks + providers wrapping platform-service APIs via fetch
- admin-web: fix ThemeEditor.tsx + themes/active/route.ts lysnrai token type access
- tracker-web: product-context import path fix (pre-existing)
2026-03-12 16:36:13 -07:00

109 lines
2.8 KiB
TypeScript

/**
* Surveys module — React context + hook for in-app surveys in React Native apps.
*/
import React, { createContext, useContext, useState, useCallback, useEffect } from 'react';
import type { PlatformSDK } from '../core.js';
export interface Question {
id: string;
text: string;
type: 'rating' | 'text' | 'choice';
options?: string[];
required: boolean;
}
export interface ActiveSurvey {
id: string;
title: string;
description?: string;
questions: Question[];
expiresAt?: string;
}
interface SurveyContextType {
activeSurvey: ActiveSurvey | null;
submit: (surveyId: string, answers: Record<string, unknown>) => Promise<void>;
dismiss: (surveyId: string) => void;
refresh: () => Promise<void>;
}
const SurveyContext = createContext<SurveyContextType | null>(null);
export function useSurveys(): SurveyContextType {
const ctx = useContext(SurveyContext);
if (!ctx) throw new Error('useSurveys must be used within a SurveyProvider');
return ctx;
}
interface SurveyProviderProps {
sdk: PlatformSDK;
/** Poll interval in ms (default: 600000 = 10 min) */
pollInterval?: number;
children: React.ReactNode;
}
export function SurveyProvider({
sdk,
pollInterval = 600_000,
children,
}: SurveyProviderProps): React.JSX.Element {
const [activeSurvey, setActiveSurvey] = useState<ActiveSurvey | null>(null);
const refresh = useCallback(async () => {
try {
const res = await sdk.fetch('/api/surveys/active');
if (res.ok) {
const data = (await res.json()) as ActiveSurvey | null;
setActiveSurvey(data ?? null);
}
} catch {
/* silent */
}
}, [sdk]);
const submit = useCallback(
async (surveyId: string, answers: Record<string, unknown>) => {
await sdk.fetch(`/api/surveys/${surveyId}/respond`, {
method: 'POST',
body: JSON.stringify({ answers }),
});
setActiveSurvey(null);
},
[sdk]
);
const dismiss = useCallback(
(surveyId: string) => {
setActiveSurvey(null);
sdk.fetch(`/api/surveys/${surveyId}/dismiss`, { method: 'POST' }).catch(() => {});
},
[sdk]
);
useEffect(() => {
refresh();
const id = setInterval(refresh, pollInterval);
return () => clearInterval(id);
}, [refresh, pollInterval]);
const value: SurveyContextType = { activeSurvey, submit, dismiss, refresh };
return React.createElement(SurveyContext.Provider, { value }, children);
}
// MARK: - UI Components
interface SurveyModalProps {
survey: ActiveSurvey | null;
onSubmit: (answers: Record<string, unknown>) => void;
onDismiss: () => void;
}
/**
* Placeholder survey modal — product apps should implement their own
* styled version. Returns null.
*/
export function SurveyModal(_props: SurveyModalProps): React.JSX.Element | null {
return null;
}