Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,681 changes: 3,681 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

128 changes: 127 additions & 1 deletion src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,16 @@ textarea {
color: var(--muted);
}

.running-research > svg {
animation: spin 0.9s linear infinite;
}

@keyframes spin {
to {
transform: rotate(360deg);
}
}

.research-result {
display: grid;
gap: 20px;
Expand Down Expand Up @@ -782,6 +792,111 @@ textarea {
background: var(--crail);
}

.research-section {
display: grid;
gap: 12px;
}

.insight-grid,
.brief-grid,
.decision-grid,
.snapshot-grid {
display: grid;
gap: 12px;
}

.insight-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}

.insight-card,
.brief-card,
.snapshot-card {
border: 1px solid var(--line);
border-radius: var(--radius);
background: var(--surface-strong);
}

.insight-card {
display: grid;
gap: 10px;
min-height: 132px;
padding: 16px;
}

.insight-card span,
.snapshot-card span {
color: var(--crail);
font-size: 0.76rem;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
}

.insight-card p,
.brief-card p,
.check-row {
color: var(--muted);
}

.snapshot-grid {
grid-template-columns: repeat(4, minmax(0, 1fr));
}

.snapshot-card {
display: grid;
gap: 4px;
min-height: 84px;
padding: 14px;
}

.snapshot-card strong {
color: var(--ink);
font-family: var(--font-display);
font-size: 1.35rem;
}

.brief-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}

.brief-card {
display: grid;
gap: 8px;
padding: 16px;
}

.brief-card h4 {
margin: 0;
color: var(--ink);
font-family: var(--font-display);
font-size: 0.98rem;
}

.decision-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}

.compact-panel {
align-content: start;
}

.check-row {
position: relative;
padding-left: 22px;
}

.check-row::before {
content: "";
position: absolute;
top: 0.7em;
left: 4px;
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--sage);
}

.result-grid {
display: grid;
grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
Expand Down Expand Up @@ -1391,6 +1506,16 @@ textarea {
.result-grid {
grid-template-columns: 1fr;
}

.insight-grid,
.brief-grid,
.decision-grid {
grid-template-columns: 1fr;
}

.snapshot-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}

@media (max-width: 720px) {
Expand Down Expand Up @@ -1436,7 +1561,8 @@ textarea {
.principle-grid,
.agent-rail,
.settings-grid,
.profile-grid {
.profile-grid,
.snapshot-grid {
grid-template-columns: 1fr;
}

Expand Down
2 changes: 1 addition & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BrowserRouter, Navigate, Route, Routes, useLocation } from 'react-router-dom'
import { AnimatePresence, motion } from 'framer-motion'
import { AnimatePresence } from 'framer-motion'
import { AuthProvider } from './components/auth/AuthProvider'
import { useTheme } from './hooks/useTheme'
import { TopNav } from './components/layout/TopNav'
Expand Down
20 changes: 16 additions & 4 deletions src/components/auth/AuthProvider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
updateProfile,
} from 'firebase/auth'
import { AuthContext } from '../../contexts/authContext'
import { auth } from '../../config/firebase'
import { auth, hasFirebaseConfig } from '../../config/firebase'

function profileKey(uid) {
return `orchide-profile-${uid}`
Expand All @@ -16,9 +16,13 @@ function profileKey(uid) {
export function AuthProvider({ children }) {
const [user, setUser] = useState(null)
const [profile, setProfile] = useState(null)
const [loading, setLoading] = useState(true)
const [loading, setLoading] = useState(hasFirebaseConfig && Boolean(auth))

useEffect(() => {
if (!hasFirebaseConfig || !auth) {
return undefined
}

return onAuthStateChanged(auth, (nextUser) => {
setUser(nextUser)
if (nextUser) {
Expand All @@ -32,18 +36,26 @@ export function AuthProvider({ children }) {
}, [])

async function signUp({ name, email, password }) {
if (!auth) {
throw new Error('Firebase auth is not configured. Add the VITE_FIREBASE_* values to a .env file.')
}

const credential = await createUserWithEmailAndPassword(auth, email, password)
await updateProfile(credential.user, { displayName: name })
setUser({ ...credential.user, displayName: name })
return credential.user
}

function signIn({ email, password }) {
if (!auth) {
throw new Error('Firebase auth is not configured. Add the VITE_FIREBASE_* values to a .env file.')
}

return signInWithEmailAndPassword(auth, email, password)
}

function saveProfile(details) {
if (!auth.currentUser) return
if (!auth?.currentUser) return
const nextProfile = {
name: details.name.trim(),
email: details.email.trim(),
Expand All @@ -64,7 +76,7 @@ export function AuthProvider({ children }) {
signUp,
signIn,
saveProfile,
signOutUser: () => signOut(auth),
signOutUser: () => (auth ? signOut(auth) : Promise.resolve()),
}), [loading, profile, user])

return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
Expand Down
11 changes: 5 additions & 6 deletions src/components/research/NewResearch.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { memo, useState, useEffect } from 'react'
import { memo, useMemo, useState } from 'react'
import { FiSearch, FiGlobe, FiTrendingUp, FiBook } from 'react-icons/fi'
import { useAuth } from '../../hooks/useAuth'

export const NewResearch = memo(function NewResearch({ onStart }) {
const { profile } = useAuth()
const [greeting, setGreeting] = useState('')
const [input, setInput] = useState('')
const [source, setSource] = useState('all')

useEffect(() => {
const greeting = useMemo(() => {
const hour = new Date().getHours()
if (hour < 12) setGreeting('Good morning')
else if (hour < 17) setGreeting('Good afternoon')
else setGreeting('Good evening')
if (hour < 12) return 'Good morning'
if (hour < 17) return 'Good afternoon'
return 'Good evening'
}, [])

const handleSubmit = (e) => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/research/ResearchInput.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const ResearchInput = memo(function ResearchInput({ input, setInput, isRu
/>
<button type="submit" disabled={isRunning || !input.trim()}>
<FiSend aria-hidden="true" />
Run
{isRunning ? 'Running' : 'Run'}
</button>
</form>
)
Expand Down
49 changes: 49 additions & 0 deletions src/components/research/ResearchResult.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,55 @@ export const ResearchResult = memo(function ResearchResult({ run }) {
<li key={bullet}>{bullet}</li>
))}
</ul>

<section className="research-section">
<h3>Key Findings</h3>
<div className="insight-grid">
{run.keyFindings.map((finding, index) => (
<div className="insight-card" key={finding}>
<span>{String(index + 1).padStart(2, '0')}</span>
<p>{finding}</p>
</div>
))}
</div>
</section>

<div className="snapshot-grid" aria-label="Research snapshot">
{run.marketSnapshot.map((item) => (
<div className="snapshot-card" key={item.label}>
<span>{item.label}</span>
<strong>{item.value}</strong>
</div>
))}
</div>

<section className="research-section">
<h3>Research Brief</h3>
<div className="brief-grid">
{run.researchBrief.map((section) => (
<article className="brief-card" key={section.title}>
<h4>{section.title}</h4>
<p>{section.text}</p>
</article>
))}
</div>
</section>

<div className="decision-grid">
<section className="sources-panel compact-panel">
<h3>Risks to Watch</h3>
{run.risks.map((risk) => (
<p className="check-row" key={risk}>{risk}</p>
))}
</section>
<section className="trace-panel compact-panel">
<h3>Next Checks</h3>
{run.nextSteps.map((step) => (
<p className="check-row" key={step}>{step}</p>
))}
</section>
</div>

<div className="result-grid">
<section className="sources-panel">
<h3>Sources</h3>
Expand Down
11 changes: 9 additions & 2 deletions src/config/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,12 @@ const firebaseConfig = {
measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
}

export const firebaseApp = initializeApp(firebaseConfig)
export const auth = getAuth(firebaseApp)
export const hasFirebaseConfig = Boolean(
firebaseConfig.apiKey &&
firebaseConfig.authDomain &&
firebaseConfig.projectId &&
firebaseConfig.appId,
)

export const firebaseApp = hasFirebaseConfig ? initializeApp(firebaseConfig) : null
export const auth = firebaseApp ? getAuth(firebaseApp) : null
Loading