anthropics / anthropics/skills

NA

Đang mở
#1,127 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
Python
Star
176k
Fork
20.8k
Merge trung bình
7 giờ 21 phút
Pull request đã merge (30 ngày)
5

Mô tả

import { useState, useRef, useEffect } from "react";

const AREAS = [
{ id: "career", label: "Career & Work", icon: "💼", color: { bg: "#E6F1FB", text: "#0C447C", border: "#85B7EB" } },
{ id: "growth", label: "Personal Growth", icon: "🌱", color: { bg: "#cdcbef", text: "#3C3489", border: "#AFA9EC" } },
{ id: "health", label: "Health & Fitness", icon: "💪", color: { bg: "#E1F5EE", text: "#085041", border: "#5DCAA5" } },
{ id: "life", label: "Life Planning", icon: "🗺️", color: { bg: "#FAEEDA", text: "#854F0B", border: "#EF9F27" } },
];

const TABS = ["Daily Advisor", "Goal Tracker", "Decide", "Coach"];

const systemPrompt = `You are a warm, insightful personal life coach and advisor. You help users with career, personal growth, health, and life planning. Be concise, practical, and encouraging. Use short paragraphs. Give actionable steps. Avoid generic advice — be specific. Never use excessive bullet points. Keep responses under 200 words unless the user needs more detail.`;

async function askClaude(messages) {
const res = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "claude-sonnet-4-20250514",
max_tokens: 1000,
system: systemPrompt,
messages,
}),
});
const data = await res.json();
return data.content?.map(b => b.text || "").join("") || "Sorry, something went wrong.";
}

function AreaBadge({ area }) {
return (
{area.icon} {area.label}
);
}

function Spinner() {
return ;
}

function AIBox({ text, loading }) {
if (!text && !loading) return null;
return (


{loading ? : text}

);
}

// ── Daily Advisor ──
function DailyAdvisor() {
const [mood, setMood] = useState("");
const [context, setContext] = useState("");
const [area, setArea] = useState(AREAS[0].id);
const [resp, setResp] = useState("");
const [loading, setLoading] = useState(false);

const ask = async () => {
if (!context.trim()) return;
setLoading(true); setResp("");
const a = AREAS.find(x => x.id === area);
const msg = `I'm feeling ${mood || "okay"} today. Area of focus: ${a.label}. Here's what's on my mind: ${context}. Give me personalized guidance and 3 clear action steps for today.`;
const r = await askClaude([{ role: "user", content: msg }]);
setResp(r); setLoading(false);
};

return (



Tell me how you're feeling and what's on your mind. I'll guide your day.



{["Great", "Good", "Okay", "Stressed", "Tired"].map(m => (
setMood(m)} style={{
fontSize: 13, padding: "5px 14px", borderRadius: 999, cursor: "pointer",
background: mood === m ? "var(--color-text-primary)" : "var(--color-background-secondary)",
color: mood === m ? "var(--color-background-primary)" : "var(--color-text-secondary)",
border: "0.5px solid var(--color-border-secondary)"
}}>{m}
))}

setArea(e.target.value)} style={{ fontSize: 13, marginBottom: 10, width: "100%" }}>
{AREAS.map(a => {a.icon} {a.label})}

setContext(e.target.value)}
placeholder="What's on your mind today? A challenge, a goal, anything..."
rows={3} style={{ width: "100%", fontSize: 14, resize: "vertical", boxSizing: "border-box" }} />
<button onClick={ask} disabled={loading || !context.trim()} style={{
marginTop: 10, width: "100%", padding: 10, fontSize: 14, fontWeight: 500,
background: "var(--color-text-primary)", color: "var(--color-background-primary)",
border: "none", borderRadius: "var(--border-radius-md)", cursor: "pointer"
}}>Guide my day →</button>
<AIBox text={resp} loading={loading} />
</div>
);
}

// ── Goal Tracker ──
function GoalTracker() {
const [goals, setGoals] = useState([]);
const [title, setTitle] = useState("");
const [area, setArea] = useState(AREAS[0].id);
const [activeGoal, setActiveGoal] = useState(null);
const [resp, setResp] = useState({});
const [loading, setLoading] = useState(null);

useEffect(() => {
window.storage.get("nav_goals").then(r => { if (r) setGoals(JSON.parse(r.value)); }).catch(() => {});
}, []);

const save = (g) => { setGoals(g); window.storage.set("nav_goals", JSON.stringify(g)).catch(() => {}); };

const addGoal = () => {
if (!title.trim()) return;
save([{ id: Date.now(), title: title.trim(), area, done: false }, ...goals]);
setTitle("");
};

const getSteps = async (goal) => {
setActiveGoal(goal.id); setLoading(goal.id);
const a = AREAS.find(x => x.id === goal.area);
const r = await askClaude([{ role: "user", content: `My goal: "${goal.title}" (area: ${a.label}). Break this into 5 concrete, achievable action steps. Number them. Be specific and motivating.` }]);
setResp(prev => ({ ...prev, [goal.id]: r })); setLoading(null);
};

return (
<div>
<p style={{ fontSize: 14, color: "var(--color-text-secondary)", marginBottom: 14 }}>
Set a goal and get AI-generated action steps to achieve it.
</p>
<div style={{ display: "flex", gap: 8, marginBottom: 12, flexWrap: "wrap" }}>
<select value={area} onChange={e => setArea(e.target.value)} style={{ fontSize: 13, flex: "0 0 auto" }}>
{AREAS.map(a => <option key={a.id} value={a.id}>{a.icon} {a.label}</option>)}
</select>
<input value={title} onChange={e => setTitle(e.target.value)} onKeyDown={e => e.key === "Enter" && addGoal()}
placeholder="Enter your goal..." style={{ fontSize: 14, flex: 1, minWidth: 180 }} />
<button onClick={addGoal} style={{
padding: "8px 16px", fontSize: 14, fontWeight: 500, borderRadius: "var(--border-radius-md)",
background: "var(--color-text-primary)", color: "var(--color-background-primary)", border: "none", cursor: "pointer"
}}>Add</button>
</div>
{goals.length === 0 && <div style={{ fontSize: 13, color: "var(--color-text-tertiary)", textAlign: "center", padding: "2rem 0" }}>No goals yet. Add one above!</div>}
<div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
{goals.map(g => {
const a = AREAS.find(x => x.id === g.area);
return (
<div key={g.id} style={{
background: "var(--color-background-primary)", border: "0.5px solid var(--color-border-tertiary)",
borderRadius: "var(--border-radius-lg)", padding: "12px 14px"
}}>
<div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 8 }}>
<input type="checkbox" checked={g.done} onChange={() => save(goals.map(x => x.id === g.id ? { ...x, done: !x.done } : x))} />
<span style={{ flex: 1, fontSize: 15, textDecoration: g.done ? "line-through" : "none", color: "var(--color-text-primary)" }}>{g.title}</span>
<AreaBadge area={a} />
<button onClick={() => save(goals.filter(x => x.id !== g.id))} style={{ background: "none", border: "none", cursor: "pointer", color: "var(--color-text-tertiary)", fontSize: 15 }}>✕</button>
</div>
<button onClick={() => getSteps(g)} disabled={loading === g.id} style={{
fontSize: 12, padding: "4px 12px", borderRadius: "var(--border-radius-md)", cursor: "pointer",
background: "var(--color-background-secondary)", border: "0.5px solid var(--color-border-secondary)",
color: "var(--color-text-secondary)"
}}>{loading === g.id ? "Thinking..." : "Get action steps →"}</button>
{activeGoal === g.id && <AIBox text={resp[g.id]} loading={loading === g.id} />}
</div>
);
})}
</div>
</div>
);
}

// ── Decision Assistant ──
function DecisionAssist() {
const [dilemma, setDilemma] = useState("");
const [optA, setOptA] = useState("");
const [optB, setOptB] = useState("");
const [resp, setResp] = useState("");
const [loading, setLoading] = useState(false);

const decide = async () => {
if (!dilemma.trim()) return;
setLoading(true); setResp("");
const msg = `I'm facing this decision: "${dilemma}". ${optA ? `Option A: ${optA}.` : ""} ${optB ? `Option B: ${optB}.` : ""} Give me a structured analysis: pros and cons of each option, key factors to consider, and your recommendation. Be honest and direct.`;
const r = await askClaude([{ role: "user", content: msg }]);
setResp(r); setLoading(false);
};

return (
<div>
<p style={{ fontSize: 14, color: "var(--color-text-secondary)", marginBottom: 14 }}>
Describe your dilemma and I'll help you think it through clearly.
</p>
<textarea value={dilemma} onChange={e => setDilemma(e.target.value)}
placeholder="Describe your decision or dilemma..." rows={3}
style={{ width: "100%", fontSize: 14, resize: "vertical", marginBottom: 10, boxSizing: "border-box" }} />
<div style={{ display: "flex", gap: 8, marginBottom: 10 }}>
<input value={optA} onChange={e => setOptA(e.target.value)} placeholder="Option A (optional)"
style={{ flex: 1, fontSize: 13 }} />
<input value={optB} onChange={e => setOptB(e.target.value)} placeholder="Option B (optional)"
style={{ flex: 1, fontSize: 13 }} />
</div>
<button onClick={decide} disabled={loading || !dilemma.trim()} style={{
width: "100%", padding: 10, fontSize: 14, fontWeight: 500,
background: "var(--color-text-primary)", color: "var(--color-background-primary)",
border: "none", borderRadius: "var(--border-radius-md)", cursor: "pointer"
}}>Analyze my decision →</button>
<AIBox text={resp} loading={loading} />
</div>
);
}

// ── Productivity Coach ──
function Coach() {
const [history, setHistory] = useState([]);
const [input, setInput] = useState("");
const [loading, setLoading] = useState(false);
const endRef = useRef(null);

const PROMPTS = [
"What should I focus on this week?",
"How do I stop procrastinating?",
"Help me build a morning routine",
"I feel overwhelmed, what do I do?",
];

useEffect(() => { endRef.current?.scrollIntoView({ behavior: "smooth" }); }, [history]);

const send = async (msg) => {
const m = msg || input.trim();
if (!m) return;
const newHistory = [...history, { role: "user", content: m }];
setHistory(newHistory); setInput(""); setLoading(true);
const r = await askClaude(newHistory);
setHistory([...newHistory, { role: "assistant", content: r }]);
setLoading(false);
};

return (
<div>
<p style={{ fontSize: 14, color: "var(--color-text-secondary)", marginBottom: 12 }}>
Chat with your personal productivity coach. Ask anything.
</p>
{history.length === 0 && (
<div style={{ display: "flex", flexDirection: "column", gap: 8, marginBottom: 16 }}>
{PROMPTS.map(p => (
<button key={p} onClick={() => send(p)} style={{
textAlign: "left", fontSize: 13, padding: "9px 14px",
background: "var(--color-background-secondary)", border: "0.5px solid var(--color-border-tertiary)",
borderRadius: "var(--border-radius-md)", cursor: "pointer", color: "var(--color-text-secondary)"
}}>{p}</button>
))}
</div>
)}
{history.length > 0 && (
<div style={{ maxHeight: 340, overflowY: "auto", marginBottom: 12, display: "flex", flexDirection: "column", gap: 10 }}>
{history.map((m, i) => (
<div key={i} style={{
alignSelf: m.role === "user" ? "flex-end" : "flex-start",
maxWidth: "85%", fontSize: 14, lineHeight: 1.6, padding: "10px 14px",
borderRadius: "var(--border-radius-lg)", whiteSpace: "pre-wrap",
background: m.role === "user" ? "var(--color-text-primary)" : "var(--color-background-secondary)",
color: m.role === "user" ? "var(--color-background-primary)" : "var(--color-text-primary)",
border: m.role === "assistant" ? "0.5px solid var(--color-border-tertiary)" : "none"
}}>{m.content}</div>
))}
{loading && <div style={{ alignSelf: "flex-start", fontSize: 13, color: "var(--color-text-tertiary)" }}><Spinner /> Thinking...</div>}
<div ref={endRef} />
</div>
)}
<div style={{ display: "flex", gap: 8 }}>
<input value={input} onChange={e => setInput(e.target.value)}
onKeyDown={e => e.key === "Enter" && !loading && send()}
placeholder="Ask your coach anything..." style={{ flex: 1, fontSize: 14 }} />
<button onClick={() => send()} disabled={loading || !input.trim()} style={{
padding: "8px 16px", fontSize: 14, fontWeight: 500,
background: "var(--color-text-primary)", color: "var(--color-background-primary)",
border: "none", borderRadius: "var(--border-radius-md)", cursor: "pointer"
}}>Send</button>
</div>
</div>
);
}

// ── Main App ──
export default function App() {
const [tab, setTab] = useState(0);
const TAB_COMPONENTS = [<DailyAdvisor />, <GoalTracker />, <DecisionAssist />, <Coach />];
const TAB_ICONS = ["☀️", "🎯", "⚖️", "🧠"];

return (
<div style={{ fontFamily: "var(--font-sans)", padding: "1.5rem 1rem", maxWidth: 680, margin: "0 auto" }}>
<style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
<div style={{ marginBottom: "1.5rem" }}>
<div style={{ fontSize: 20, fontWeight: 500, color: "var(--color-text-primary)" }}>Personal Life Navigator</div>
<div style={{ fontSize: 13, color: "var(--color-text-secondary)", marginTop: 2 }}>Your AI-powered guide for every area of life</div>
</div>

{/* Area pills */}
<div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: "1.25rem" }}>
{AREAS.map(a => <AreaBadge key={a.id} area={a} />)}
</div>

{/* Tabs */}
<div style={{ display: "flex", gap: 4, marginBottom: "1.25rem", borderBottom: "0.5px solid var(--color-border-tertiary)", paddingBottom: 0 }}>
{TABS.map((t, i) => (
<button key={t} onClick={() => setTab(i)} style={{
fontSize: 13, padding: "8px 14px", cursor: "pointer", fontWeight: tab === i ? 500 : 400,
background: "none", border: "none",
borderBottom: tab === i ? "2px solid var(--color-text-primary)" : "2px solid transparent",
color: tab === i ? "var(--color-text-primary)" : "var(--color-text-secondary)",
marginBottom: -1
}}>{TAB_ICONS[i]} {t}</button>
))}
</div>

{/* Content */}
<div>{TAB_COMPONENTS[tab]}</div>
</div>
);
}

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.