| import gradio as gr |
| import pandas as pd |
| import plotly.express as px |
|
|
| df = pd.read_csv("sample_100_jobs.csv") |
|
|
| def filter_data(industry, country, max_risk, min_salary): |
| d = df.copy() |
| if industry != "All": d = d[d["Industry"] == industry] |
| if country != "All": d = d[d["Country"] == country] |
| d = d[(d["AI_Replacement_Risk"] <= max_risk) & (d["Average_Salary_USD"] >= min_salary)] |
| return d.sort_values("Demand_Risk_Ratio", ascending=False) |
|
|
| def scatter(): |
| fig = px.scatter(df, x="AI_Replacement_Risk", y="Average_Salary_USD", |
| color="AI_Risk_Category", size="Demand_Risk_Ratio", |
| hover_data=["Job_Title"], template="plotly_dark", height=420, |
| color_discrete_map={"Low":"#10B981","Medium":"#3B82F6","High":"#EF4444"}) |
| fig.update_layout( |
| paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)", |
| margin=dict(l=10,r=10,t=40,b=10), font=dict(family="Inter") |
| ) |
| return fig |
|
|
| def top_jobs(): |
| top = df.nlargest(10, "Demand_Risk_Ratio") |
| fig = px.bar(top, x="Demand_Risk_Ratio", y="Job_Title", orientation="h", |
| template="plotly_dark", color="Demand_Risk_Ratio", height=420, |
| color_continuous_scale="Viridis") |
| fig.update_layout( |
| paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)", |
| yaxis={"categoryorder":"total ascending"}, font=dict(family="Inter") |
| ) |
| return fig |
|
|
| css = """ |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap'); |
| |
| * {font-family: 'Inter', sans-serif !important;} |
| |
| body{ |
| background: radial-gradient(ellipse 80% 50% at 50% -20%, rgba(120,119,198,0.3), transparent), |
| radial-gradient(ellipse 80% 50% at 50% 120%, rgba(79,70,229,0.2), transparent), |
| linear-gradient(180deg, #020617 0%, #0F172A 50%, #020617 100%) !important; |
| background-attachment: fixed !important; |
| } |
| |
| .gradio-container{ |
| width:96% !important; |
| max-width:1400px !important; |
| margin: 0 auto !important; |
| } |
| |
| /* ANIMASI GRADIENT BERJALAN */ |
| @keyframes gradientFlow { |
| 0% {background-position: 0% 50%;} |
| 50% {background-position: 100% 50%;} |
| 100% {background-position: 0% 50%;} |
| } |
| |
| .animated-gradient { |
| background: linear-gradient(90deg, #60A5FA, #A855F7, #EC4899, #60A5FA); |
| background-size: 300% 300%; |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| animation: gradientFlow 4s ease infinite; |
| } |
| |
| /* NAVBAR */ |
| .navbar{ |
| display: flex;justify-content: space-between;align-items: center; |
| padding: 20px 0;margin-bottom: 30px; |
| } |
| .nav-left{display:flex;align-items:center;gap:40px} |
| .logo{display:flex;align-items:center;gap:12px;font-weight:900;font-size:22px;color:#fff} |
| .logo-icon{ |
| width:32px;height:32px;border-radius:8px; |
| background:linear-gradient(135deg,#6366F1,#A855F7); |
| display:flex;align-items:center;justify-content:center; |
| box-shadow:0 0 20px rgba(99,102,241,.6); |
| } |
| .nav-links{display:flex;gap:32px} |
| .nav-links a{color:#94A3B8;text-decoration:none;font-weight:600;font-size:14px} |
| .nav-links a:hover{color:#fff} |
| .nav-right{display:flex;gap:12px} |
| .btn-ghost{ |
| background:rgba(30,41,59,.6);border:1px solid rgba(99,102,241,.3); |
| color:#fff;padding:10px 20px;border-radius:12px;font-weight:700;cursor:pointer; |
| } |
| .btn-primary{ |
| background:linear-gradient(90deg,#6366F1,#A855F7); |
| color:#fff;padding:10px 24px;border-radius:12px;border:none; |
| font-weight:700;cursor:pointer; |
| box-shadow:0 4px 20px rgba(99,102,241,.4), 0 0 40px rgba(99,102,241,.2); |
| } |
| |
| /* HERO */ |
| .hero{ |
| padding:70px 45px; |
| border-radius:24px; |
| background: linear-gradient(135deg, rgba(15,23,42,.8), rgba(30,41,59,.6)); |
| border:1px solid rgba(99,102,241,.2); |
| box-shadow: 0 0 60px rgba(99,102,241,.15), inset 0 1px 0 rgba(255,255,255,.1); |
| margin-bottom:40px; |
| text-align: center; |
| backdrop-filter: blur(20px); |
| position:relative;overflow:hidden; |
| } |
| .hero::before{ |
| content:'';position:absolute;top:-50%;left:50%;transform:translateX(-50%); |
| width:600px;height:600px; |
| background:radial-gradient(circle, rgba(99,102,241,.25), transparent 70%); |
| filter:blur(80px);z-index:0; |
| } |
| .hero-badge{ |
| display:inline-flex;align-items:center;gap:8px; |
| padding:8px 16px;background:rgba(99,102,241,.1); |
| border:1px solid rgba(99,102,241,.3);border-radius:99px; |
| font-size:14px;color:#A5B4FC;margin-bottom:24px;position:relative;z-index:1;font-weight:600; |
| } |
| .hero h1{ |
| font-size:68px;line-height:1.1;font-weight:900; |
| margin:0 0 16px 0;position:relative;z-index:1; |
| color:#FFFFFF; |
| letter-spacing:-1px; |
| } |
| .hero h1 .gradient{ |
| font-weight:900; |
| display:block; |
| margin-top:8px; |
| } |
| .hero p{ |
| font-size:18px;color:#CBD5E1;max-width:700px; |
| margin:0 auto 32px auto;line-height:1.7;position:relative;z-index:1;font-weight:500; |
| } |
| .hero-cta{display:flex;gap:16px;justify-content:center;position:relative;z-index:1} |
| |
| /* STATS */ |
| .stats{ |
| display: grid; |
| grid-template-columns: repeat(4, 1fr); |
| gap: 20px; |
| margin-bottom: 80px; |
| } |
| .stat-card{ |
| padding:28px 24px; |
| border-radius:20px; |
| background: linear-gradient(135deg, rgba(99,102,241,.1), rgba(168,85,247,.05)); |
| backdrop-filter: blur(20px); |
| border: 1px solid rgba(99,102,241,.2); |
| text-align: center; |
| box-shadow: 0 8px 32px rgba(99,102,241,.1); |
| } |
| .stat-card .label{ |
| display:flex;align-items:center;gap:8px;justify-content:center; |
| color:#94A3B8;font-size:14px;margin-bottom:12px;font-weight:600; |
| } |
| .stat-card .value{ |
| font-size:36px;font-weight:900; |
| background: linear-gradient(90deg, #6366F1, #A855F7); |
| -webkit-background-clip: text; |
| -webkit-text-fill-color: transparent; |
| } |
| |
| /* DASHBOARD */ |
| .section-header{margin-bottom:32px} |
| .section-header h2{font-size:32px;margin:0 0 8px 0;font-weight:900;color:#fff} |
| .section-header p{color:#94A3B8;margin:0;font-size:15px;font-weight:500} |
| .card{ |
| padding:24px;border-radius:20px; |
| background: rgba(15,23,42,.6) !important; |
| backdrop-filter: blur(20px) !important; |
| border: 1px solid rgba(99,102,241,.15) !important; |
| margin-bottom:24px;box-shadow: 0 8px 32px rgba(0,0,0,.3); |
| } |
| |
| .footer{ |
| margin-top:60px;padding:40px 30px;text-align:center; |
| color: #64748B;border-top: 1px solid rgba(99,102,241,.1);font-weight: 600; |
| } |
| |
| @media (max-width: 768px) { |
| .nav-links{display:none} |
| .hero h1 { font-size: 42px; } |
| .stats { grid-template-columns: repeat(2, 1fr); } |
| .hero-cta{flex-direction:column} |
| } |
| """ |
|
|
| with gr.Blocks(css=css, fill_width=True, theme=gr.themes.Base()) as demo: |
| |
| |
| gr.HTML(""" |
| <div class='navbar'> |
| <div class='nav-left'> |
| <div class='logo'> |
| <div class='logo-icon'>β</div> |
| AI DataLab |
| </div> |
| <div class='nav-links'> |
| <a href='#dashboard'>Dashboard</a> |
| <a href='#'>Reports</a> |
| <a href='#'>Insights</a> |
| <a href='#'>About</a> |
| </div> |
| </div> |
| <div class='nav-right'> |
| <button class='btn-ghost'>Sign In</button> |
| <button class='btn-primary'>Get Started</button> |
| </div> |
| </div> |
| """) |
|
|
| |
| gr.HTML(""" |
| <div class='hero'> |
| <div class='hero-badge'>β
Powered by AI-Driven Analytics</div> |
| <h1> |
| Future-Proof Your Career |
| <span class='gradient animated-gradient'>with AI Insights</span> |
| </h1> |
| <p> |
| Analyze job market trends, salary projections, and AI automation risks. |
| Make data-driven decisions for 2031 and beyond with real-time predictive analytics. |
| </p> |
| <div class='hero-cta'> |
| <button class='btn-primary' onclick="document.getElementById('dashboard').scrollIntoView({behavior:'smooth'})"> |
| Explore Dashboard β |
| </button> |
| <button class='btn-ghost'>βΆ Watch Demo</button> |
| </div> |
| </div> |
| """) |
|
|
| |
| gr.HTML(""" |
| <div class='stats'> |
| <div class='stat-card'> |
| <div class='label'>β‘ Total Jobs Analyzed</div> |
| <div class='value'>3,000+</div> |
| </div> |
| <div class='stat-card'> |
| <div class='label'>$ Average Salary 2031</div> |
| <div class='value'>$96K</div> |
| </div> |
| <div class='stat-card'> |
| <div class='label'>β High Risk Jobs</div> |
| <div class='value'>856</div> |
| </div> |
| <div class='stat-card'> |
| <div class='label'>β¦ Future-Proof Score</div> |
| <div class='value'>87.5%</div> |
| </div> |
| </div> |
| """) |
| |
| |
| gr.HTML(""" |
| <div class='section-header' id='dashboard'> |
| <h2>Live Data Analysis Dashboard</h2> |
| <p>Filter and explore 100+ jobs with real-time risk scoring</p> |
| </div> |
| """) |
|
|
| with gr.Row(): |
| with gr.Column(scale=1, min_width=300): |
| with gr.Group(elem_classes="card"): |
| gr.Markdown("### π FILTERS") |
| industry = gr.Dropdown(["All"] + sorted(df["Industry"].unique()), value="All", label="Industry") |
| country = gr.Dropdown(["All"] + sorted(df["Country"].unique()), value="All", label="Country") |
| risk = gr.Slider(0, 1, value=.5, label="Max AI Risk") |
| salary = gr.Slider(0, 200000, value=50000, label="Min Salary (USD)") |
| btn = gr.Button("Analyze Data β", variant="primary") |
|
|
| with gr.Column(scale=4): |
| with gr.Group(elem_classes="card"): |
| gr.Plot(value=scatter()) |
| with gr.Group(elem_classes="card"): |
| gr.Plot(value=top_jobs()) |
| with gr.Group(elem_classes="card"): |
| gr.Markdown("### π Job Dataset") |
| table = gr.Dataframe(value=df.head(20), interactive=False) |
|
|
| btn.click(filter_data, [industry,country,risk,salary], table) |
|
|
| |
| gr.HTML(""" |
| <div class='footer'> |
| <div style='margin-bottom:24px;'> |
| <h3 style='font-size:20px;font-weight:800;margin:0 0 8px 0;color:#fff;'>π¨βπ» Author</h3> |
| <p style='font-size:18px;font-weight:700;margin:0 0 4px 0;color:#E2E8F0;'>Farly Setiawan</p> |
| <p style='font-size:14px;margin:0 0 16px 0;color:#94A3B8;'>Founder @ Aitopia | Specialist Data Engineer</p> |
| <p style='font-size:14px;margin:0 0 20px 0;color:#64748B;'>Helping 2M Indonesian traders lose less money</p> |
| </div> |
| |
| <div style='display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-bottom:24px;'> |
| <a href='https://www.linkedin.com/in/faronecapital' target='_blank'> |
| <img src='https://img.shields.io/badge/LinkedIn-Farly_Setiawan-0077B5?style=for-the-badge&logo=linkedin&logoColor=white'> |
| </a> |
| <a href='https://huggingface.co/farone11' target='_blank'> |
| <img src='https://img.shields.io/badge/π€_Hugging_Face-farone11-yellow?style=for-the-badge'> |
| </a> |
| <a href='https://github.com/farone11' target='_blank'> |
| <img src='https://img.shields.io/badge/GitHub-farone11-181717?style=for-the-badge&logo=github'> |
| </a> |
| </div> |
| |
| <div style='padding-top:24px;border-top:1px solid rgba(99,102,241,.1);'> |
| <p style='font-size:13px;margin:0 0 8px 0;color:#64748B;font-weight:600;'>π License</p> |
| <p style='font-size:13px;margin:0;color:#475569;'> |
| Commercial License Required. Demo is free for evaluation.<br> |
| Full datasheet & source code require purchase. Contact farone2013@gmail.com |
| </p> |
| </div> |
| |
| <div style='margin-top:24px;font-size:12px;color:#475569;'> |
| Β© 2026 FarOneCapital Institutional Analytics Platform |
| </div> |
| </div> |
| """) |
|
|
| demo.launch() |