Fix the frontend API calls and implement logins on frontend #7
@@ -42,3 +42,24 @@ textarea:focus {
|
||||
box-shadow: 0 0 0 3px var(--focus-ring);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@keyframes stats-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes stats-pulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,27 @@ const StatPage = () => {
|
||||
getStats();
|
||||
}, [datasetId])
|
||||
|
||||
if (loading) return <p style={{...styles.page, minWidth: "100vh", minHeight: "100vh"}}>Loading insights…</p>;
|
||||
if (loading) {
|
||||
return (
|
||||
<div style={styles.loadingPage}>
|
||||
<div style={styles.loadingCard}>
|
||||
<div style={styles.loadingHeader}>
|
||||
<div style={styles.loadingSpinner} />
|
||||
<div>
|
||||
<h2 style={styles.loadingTitle}>Loading analytics</h2>
|
||||
<p style={styles.loadingSubtitle}>Fetching summary, timeline, user, and content insights.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={styles.loadingSkeleton}>
|
||||
<div style={{ ...styles.loadingSkeletonLine, ...styles.loadingSkeletonLineLong }} />
|
||||
<div style={{ ...styles.loadingSkeletonLine, ...styles.loadingSkeletonLineMed }} />
|
||||
<div style={{ ...styles.loadingSkeletonLine, ...styles.loadingSkeletonLineShort }} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (error) return <p style={{...styles.page}}>{error}</p>;
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,6 +2,78 @@ import { palette } from "./palette";
|
||||
import type { StyleMap } from "./types";
|
||||
|
||||
export const feedbackStyles: StyleMap = {
|
||||
loadingPage: {
|
||||
width: "100%",
|
||||
minHeight: "100vh",
|
||||
padding: 20,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
|
||||
loadingCard: {
|
||||
width: "min(560px, 92vw)",
|
||||
background: palette.surface,
|
||||
border: `1px solid ${palette.borderDefault}`,
|
||||
borderRadius: 8,
|
||||
boxShadow: `0 1px 0 ${palette.shadowSubtle}`,
|
||||
padding: 20,
|
||||
},
|
||||
|
||||
loadingHeader: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 12,
|
||||
},
|
||||
|
||||
loadingSpinner: {
|
||||
width: 18,
|
||||
height: 18,
|
||||
borderRadius: "50%",
|
||||
border: `2px solid ${palette.borderDefault}`,
|
||||
borderTopColor: palette.brandGreen,
|
||||
animation: "stats-spin 0.9s linear infinite",
|
||||
flexShrink: 0,
|
||||
},
|
||||
|
||||
loadingTitle: {
|
||||
margin: 0,
|
||||
fontSize: 16,
|
||||
fontWeight: 600,
|
||||
color: palette.textPrimary,
|
||||
},
|
||||
|
||||
loadingSubtitle: {
|
||||
margin: "6px 0 0",
|
||||
fontSize: 13,
|
||||
color: palette.textSecondary,
|
||||
},
|
||||
|
||||
loadingSkeleton: {
|
||||
marginTop: 16,
|
||||
display: "grid",
|
||||
gap: 8,
|
||||
},
|
||||
|
||||
loadingSkeletonLine: {
|
||||
height: 9,
|
||||
borderRadius: 999,
|
||||
background: palette.canvas,
|
||||
animation: "stats-pulse 1.25s ease-in-out infinite",
|
||||
},
|
||||
|
||||
loadingSkeletonLineLong: {
|
||||
width: "100%",
|
||||
},
|
||||
|
||||
loadingSkeletonLineMed: {
|
||||
width: "78%",
|
||||
},
|
||||
|
||||
loadingSkeletonLineShort: {
|
||||
width: "62%",
|
||||
},
|
||||
|
||||
alertCardError: {
|
||||
borderColor: palette.alertErrorBorder,
|
||||
background: palette.alertErrorBg,
|
||||
|
||||
@@ -55,16 +55,24 @@ type TimeAnalysisResponse = {
|
||||
}
|
||||
|
||||
// Content Analysis
|
||||
type Emotion = {
|
||||
emotion_anger: number;
|
||||
emotion_disgust: number;
|
||||
emotion_fear: number;
|
||||
emotion_joy: number;
|
||||
emotion_sadness: number;
|
||||
};
|
||||
|
||||
type NGram = {
|
||||
count: number;
|
||||
ngram: string;
|
||||
}
|
||||
|
||||
type AverageEmotionByTopic = {
|
||||
topic: string;
|
||||
n: number;
|
||||
[emotion: string]: string | number;
|
||||
}
|
||||
type AverageEmotionByTopic = Emotion & {
|
||||
n: number;
|
||||
topic: string;
|
||||
};
|
||||
|
||||
|
||||
type ContentAnalysisResponse = {
|
||||
word_frequencies: FrequencyWord[];
|
||||
|
||||
Reference in New Issue
Block a user