PrepGrid / app.py
HARISARAVANANM's picture
Upload 3 files
c9341c6 verified
import gradio as gr
import json
import os
from datetime import datetime
from typing import Dict, List, Tuple
DATA_FILE = "prepgrid_data.json"
def load_data() -> Dict:
if os.path.exists(DATA_FILE):
with open(DATA_FILE, "r") as f:
return json.load(f)
return {"users": {}, "sessions": []}
def save_data(data: Dict):
with open(DATA_FILE, "w") as f:
json.dump(data, f, indent=2)
def calculate_score(criteria: Dict) -> Tuple[int, str]:
total = sum(criteria.values())
max_score = len(criteria) * 10
percentage = (total / max_score) * 100
if percentage >= 90:
return int(percentage), " Excellent "
elif percentage >= 75:
return int(percentage), " Good "
elif percentage >= 60:
return int(percentage), " Average "
elif percentage >= 40:
return int(percentage), " Needs Improvement "
else:
return int(percentage), " Needs Work "
def get_color_for_score(score: int) -> str:
if score >= 90:
return "#10b981"
elif score >= 75:
return "#22c55e"
elif score >= 60:
return "#eab308"
elif score >= 40:
return "#f97316"
else:
return "#ef4444"
theme_css = """
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
:root {
--primary: #6366f1;
--primary-dark: #4f46e5;
--success: #10b981;
--warning: #f59e0b;
--danger: #ef4444;
--bg-dark: #0f172a;
--bg-card: #1e293b;
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
}
.gradio-container {
font-family: 'Inter', sans-serif !important;
}
.main-container {
background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%) !important;
min-height: 100vh;
padding: 20px;
}
.hero-section {
text-align: center;
padding: 40px 20px;
background: linear-gradient(135deg, rgba(99, 102, 241, 0.2) 0%, rgba(139, 92, 246, 0.1) 100%);
border-radius: 20px;
margin-bottom: 30px;
border: 1px solid rgba(99, 102, 241, 0.3);
}
.hero-title {
font-size: 3em !important;
font-weight: 700 !important;
background: linear-gradient(135deg, #818cf8, #c084fc, #f472b6) !important;
-webkit-background-clip: text !important;
-webkit-text-fill-color: transparent !important;
margin-bottom: 10px !important;
}
.hero-subtitle {
font-size: 1.3em !important;
color: #cbd5e1 !important;
margin-bottom: 20px !important;
}
.card {
background: linear-gradient(145deg, #1e293b 0%, #0f172a 100%) !important;
border-radius: 16px !important;
padding: 24px !important;
border: 1px solid rgba(99, 102, 241, 0.2) !important;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3) !important;
margin-bottom: 20px !important;
}
.card-title {
font-size: 1.4em !important;
font-weight: 600 !important;
color: #e2e8f0 !important;
margin-bottom: 16px !important;
display: flex !important;
align-items: center !important;
gap: 10px !important;
}
.plan-badge {
padding: 6px 16px;
border-radius: 20px;
font-size: 0.85em;
font-weight: 600;
text-transform: uppercase;
}
.plan-free {
background: linear-gradient(135deg, #64748b, #475569) !important;
color: white !important;
}
.plan-pro {
background: linear-gradient(135deg, #f59e0b, #d97706) !important;
color: white !important;
box-shadow: 0 0 20px rgba(245, 158, 11, 0.4) !important;
}
.stat-card {
background: rgba(30, 41, 59, 0.8) !important;
border-radius: 12px !important;
padding: 20px !important;
text-align: center !important;
border: 1px solid rgba(99, 102, 241, 0.2) !important;
transition: transform 0.2s, box-shadow 0.2s;
}
.stat-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 40px rgba(99, 102, 241, 0.3) !important;
}
.stat-value {
font-size: 2.5em !important;
font-weight: 700 !important;
margin-bottom: 4px !important;
}
.stat-label {
font-size: 0.9em !important;
color: #94a3b8 !important;
text-transform: uppercase;
letter-spacing: 1px;
}
.btn-primary {
background: linear-gradient(135deg, #6366f1, #8b5cf6) !important;
color: white !important;
border: none !important;
padding: 14px 28px !important;
border-radius: 12px !important;
font-weight: 600 !important;
font-size: 1em !important;
transition: all 0.3s !important;
box-shadow: 0 4px 20px rgba(99, 102, 241, 0.4) !important;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 30px rgba(99, 102, 241, 0.5) !important;
}
.btn-secondary {
background: rgba(99, 102, 241, 0.1) !important;
color: #818cf8 !important;
border: 1px solid rgba(99, 102, 241, 0.3) !important;
padding: 14px 28px !important;
border-radius: 12px !important;
font-weight: 600 !important;
}
.score-excellent { color: #10b981 !important; }
.score-good { color: #22c55e !important; }
.score-average { color: #eab308 !important; }
.score-needs { color: #f97316 !important; }
.score-poor { color: #ef4444 !important; }
.progress-bar {
height: 12px;
background: #1e293b;
border-radius: 6px;
overflow: hidden;
}
.progress-fill {
height: 100%;
border-radius: 6px;
transition: width 0.5s ease;
}
.tab-btn {
padding: 12px 24px !important;
border-radius: 10px !important;
font-weight: 500 !important;
transition: all 0.2s !important;
}
.tab-btn.selected {
background: linear-gradient(135deg, #6366f1, #8b5cf6) !important;
color: white !important;
}
.criteria-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
background: rgba(30, 41, 59, 0.5);
border-radius: 10px;
margin-bottom: 10px;
border: 1px solid rgba(99, 102, 241, 0.1);
}
.criteria-label {
font-weight: 500;
color: #e2e8f0;
}
.slider-container {
padding: 10px 0;
}
.feedback-box {
background: rgba(30, 41, 59, 0.6);
border-radius: 12px;
padding: 20px;
border-left: 4px solid #6366f1;
margin-top: 20px;
}
.code-editor {
font-family: 'JetBrains Mono', 'Fira Code', monospace !important;
background: #0d1117 !important;
border: 1px solid #30363d !important;
border-radius: 12px !important;
min-height: 300px !important;
}
.mock-question {
background: linear-gradient(135deg, rgba(99, 102, 241, 0.1), rgba(139, 92, 246, 0.05));
border-radius: 12px;
padding: 20px;
margin-bottom: 16px;
border: 1px solid rgba(99, 102, 241, 0.2);
}
.mock-question-title {
font-weight: 600;
color: #818cf8;
margin-bottom: 8px;
}
.mock-question-text {
color: #e2e8f0;
line-height: 1.6;
}
.tips-list {
list-style: none;
padding: 0;
}
.tips-list li {
padding: 12px 16px;
margin-bottom: 8px;
background: rgba(16, 185, 129, 0.1);
border-radius: 8px;
border-left: 3px solid #10b981;
color: #a7f3d0;
}
.nav-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
background: rgba(15, 23, 42, 0.9);
border-bottom: 1px solid rgba(99, 102, 241, 0.2);
margin: -20px -20px 20px -20px;
border-radius: 20px 20px 0 0;
}
.brand-name {
font-weight: 700;
font-size: 1.5em;
background: linear-gradient(135deg, #818cf8, #c084fc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
"""
def create_header():
with gr.Row(elem_classes="nav-header"):
with gr.Column(scale=1):
gr.Markdown("**PrepGrid**", elem_classes="brand-name")
with gr.Column(scale=2):
gr.Markdown("### Interview Performance Tracker", elem_classes="brand-name")
with gr.Column(scale=1):
gr.Markdown("πŸš€")
def landing_page():
with gr.Column(elem_classes="main-container"):
create_header()
with gr.Row(elem_classes="hero-section"):
gr.Markdown("## 🎯 PrepGrid", elem_classes="hero-title")
gr.Markdown("Master your interviews with AI-powered practice and tracking", elem_classes="hero-subtitle")
gr.Markdown("""
### Your Interview Journey Starts Here
- πŸ“ **Mock Interviews** - Practice with real interview questions
- πŸ’» **Code Challenges** - Sharpen your coding skills
- πŸ“Š **Performance Tracking** - Track your progress over time
- πŸŽ“ **AI Feedback** - Get personalized improvement tips
""")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("""
<div class="card">
<div class="card-title">πŸ“‹ Free Plan</div>
<span class="plan-badge plan-free">Free</span>
- βœ… 5 Mock Interviews/month
- βœ… Basic Code Challenges
- βœ… Performance Dashboard
- βœ… Community Support
<br><br>
*Perfect for getting started*
</div>
""", elem_classes="card")
with gr.Column(scale=1):
gr.Markdown("""
<div class="card">
<div class="card-title">⭐ Pro Plan</div>
<span class="plan-badge plan-pro">Pro</span>
- βœ… Unlimited Mock Interviews
- βœ… Advanced Code Challenges
- βœ… AI-Powered Feedback
- βœ… Priority Support
- βœ… Custom Practice Sessions
- βœ… Resume Review
<br><br>
*$9.99/month - Best for serious candidates*
</div>
""", elem_classes="card")
with gr.Row():
gr.Markdown("### πŸš€ Get Started", elem_classes="card-title")
with gr.Row():
with gr.Column():
gr.Button("Start Free Practice", variant="primary", size="lg").click(lambda: "practice", _js="() => 'practice'")
with gr.Column():
gr.Button("Upgrade to Pro", variant="secondary", size="lg")
def practice_page():
data = load_data()
with gr.Column(elem_classes="main-container"):
create_header()
with gr.Tabs():
with gr.Tab("πŸ“ Mock Interview"):
gr.Markdown("## 🎀 Mock Interview Practice", elem_classes="card-title")
with gr.Row():
with gr.Column(scale=2):
category = gr.Dropdown(
choices=["Behavioral", "Technical", "System Design", "Case Study", "Leadership"],
label="Interview Type",
value="Behavioral"
)
with gr.Column(scale=1):
difficulty = gr.Dropdown(
choices=["Easy", "Medium", "Hard"],
label="Difficulty",
value="Medium"
)
with gr.Row():
question_text = gr.Textbox(
label="Interview Question",
value="Tell me about a time you had to deal with a difficult team member. How did you handle it?",
lines=4
)
with gr.Row():
response_box = gr.Textbox(
label="Your Response",
placeholder="Practice your answer here...",
lines=6
)
with gr.Row():
submit_btn = gr.Button("Submit Response", variant="primary", size="lg")
with gr.Row():
feedback_area = gr.Markdown("""
<div class="feedback-box">
<strong>πŸ’‘ Tips for improvement:</strong>
<ul>
<li>Use the STAR method (Situation, Task, Action, Result)</li>
<li>Be specific with examples from your experience</li>
<li>Quantify your achievements when possible</li>
<li>Practice speaking aloud to improve delivery</li>
</ul>
</div>
""")
with gr.Tab("πŸ’» Code Challenge"):
gr.Markdown("## πŸ’» Coding Practice", elem_classes="card-title")
with gr.Row():
with gr.Column(scale=2):
language = gr.Dropdown(
choices=["Python", "JavaScript", "Java", "C++", "Go"],
label="Language",
value="Python"
)
with gr.Column(scale=1):
topic = gr.Dropdown(
choices=["Arrays", "Strings", "Trees", "Graphs", "DP", "Sorting"],
label="Topic",
value="Arrays"
)
gr.Markdown("""
<div class="mock-question">
<div class="mock-question-title">πŸ“Œ Challenge: Two Sum</div>
<div class="mock-question-text">
Given an array of integers `nums` and an integer `target`, return indices of the two numbers such that they add up to `target`.
<br><br>
You may assume that each input would have exactly one solution, and you may not use the same element twice.
<br><br>
<strong>Example:</strong><br>
Input: nums = [2,7,11,15], target = 9<br>
Output: [0,1]<br>
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
</div>
</div>
""")
code_editor = gr.Codebox(
label="Your Code",
language="python",
value="def two_sum(nums, target):\n # Write your solution here\n pass",
lines=15,
elem_classes="code-editor"
)
run_btn = gr.Button("Run Code", variant="primary", size="lg")
with gr.Row():
output_area = gr.Textbox(label="Output", lines=4)
with gr.Tab("πŸ“Š Performance Dashboard"):
gr.Markdown("## πŸ“Š Your Performance", elem_classes="card-title")
with gr.Row():
with gr.Column():
gr.Markdown(f"""
<div class="stat-card">
<div class="stat-value" style="color: #22c55e;">{data.get('total_sessions', 0)}</div>
<div class="stat-label">Sessions Completed</div>
</div>
""")
with gr.Column():
gr.Markdown(f"""
<div class="stat-card">
<div class="stat-value" style="color: #6366f1;">{data.get('avg_score', 0)}%</div>
<div class="stat-label">Average Score</div>
</div>
""")
with gr.Column():
gr.Markdown(f"""
<div class="stat-card">
<div class="stat-value" style="color: #f59e0b;">0</div>
<div class="stat-label">Streak Days</div>
</div>
""")
gr.Markdown("### Recent Sessions", elem_classes="card-title")
gr.Markdown("""
| Date | Type | Score | Status |
|------|------|-------|---------|
| No sessions yet | - | - | - |
""")
with gr.Accordion("πŸ“ˆ Detailed Analysis", open=True):
gr.Markdown("""
### Scoring Criteria
1. **Communication** (0-10): How clearly did you express your thoughts?
2. **Content Quality** (0-10): How relevant and comprehensive was your answer?
3. **Examples** (0-10): Did you use concrete examples to support your points?
4. **Confidence** (0-10): How confident did you sound during the response?
5. **Structure** (0-10): Was your answer well-organized and easy to follow?
""")
comm = gr.Slider(0, 10, 7, step=1, label="Communication", interactive=True)
content = gr.Slider(0, 10, 7, step=1, label="Content Quality", interactive=True)
examples = gr.Slider(0, 10, 7, step=1, label="Examples", interactive=True)
confidence = gr.Slider(0, 10, 7, step=1, label="Confidence", interactive=True)
structure = gr.Slider(0, 10, 7, step=1, label="Structure", interactive=True)
calc_btn = gr.Button("Calculate Score", variant="primary")
score_output = gr.Markdown("")
def update_score(c, co, ex, con, st):
criteria = {
"Communication": c,
"Content Quality": co,
"Examples": ex,
"Confidence": con,
"Structure": st
}
score, grade = calculate_score(criteria)
color = get_color_for_score(score)
return f"""
<div class="stat-card">
<div class="stat-value" style="color: {color};">{score}%</div>
<div class="stat-label">{grade}</div>
</div>
"""
calc_btn.click(
update_score,
inputs=[comm, content, examples, confidence, structure],
outputs=[score_output]
)
with gr.Tab("πŸ’‘ Tips & Resources"):
gr.Markdown("## πŸ’‘ Interview Tips", elem_classes="card-title")
gr.Markdown("""
<ul class="tips-list">
<li>🎯 <strong>Research the company</strong> - Know their mission, recent news, and culture</li>
<li>πŸ“ <strong>Practice STAR method</strong> - Structure behavioral answers effectively</li>
<li>πŸ’» <strong>Code daily</strong> - Consistent practice builds muscle memory</li>
<li>🎀 <strong>Mock with friends</strong> - Practice speaking your answers aloud</li>
<li>😴 <strong>Rest well</strong> - Be energized for interview day</li>
<li>πŸ“‹ <strong>Prepare questions</strong> - Have 3-5 thoughtful questions for the interviewer</li>
<li>🎨 <strong>Dress appropriately</strong> - When in doubt, dress one level up</li>
<li>⏰ <strong>Time management</strong> - Don't spend too long on any single question</li>
</ul>
""")
gr.Markdown("### Recommended Resources", elem_classes="card-title")
gr.Markdown("""
- LeetCode for coding practice
- HackerRank for timed challenges
- Pramp for mock interviews
- Exponent for system design
""")
def main():
demo = gr.TabbedInterface(
[landing_page, practice_page],
["🏠 Home", "🎯 Practice"],
title="PrepGrid - Interview Performance Tracker",
theme=gr.themes.Soft(),
css=theme_css
)
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=True
)
if __name__ == "__main__":
main()