2026-05-10 07:08:12 +00:00
{% extends "base.html" %}
{% block extra_head %}
2026-05-12 13:07:34 +00:00
< link rel = "stylesheet" href = "/static/css/feed.css" >
2026-05-10 07:08:12 +00:00
< link rel = "stylesheet" href = "/static/css/projects.css" >
2026-05-12 11:08:38 +00:00
< link rel = "stylesheet" href = "/static/css/sidebar.css" >
2026-05-10 07:08:12 +00:00
{% endblock %}
{% block content %}
< div class = "projects-layout" >
2026-05-12 11:08:38 +00:00
< aside class = "sidebar-card" >
< div class = "sidebar-heading" > Filter</ div >
< div class = "sidebar-section" >
2026-05-10 07:08:12 +00:00
< form method = "GET" action = "/projects" >
< input type = "text" name = "search" placeholder = "Search projects..." value = "{{ search }}" >
</ form >
</ div >
2026-05-12 11:08:38 +00:00
< div class = "sidebar-section" >
< div class = "sidebar-heading" > Type</ div >
< div class = "sidebar-nav" >
2026-05-12 13:07:34 +00:00
< a href = "/projects?tab={{ current_tab }}" class = "sidebar-link {% if not project_type %}active{% endif %}" >< span class = "icon" > 📋 </ span > All</ a >
< a href = "/projects?tab={{ current_tab }}&type=game" class = "sidebar-link {% if project_type == 'game' %}active{% endif %}" >< span class = "icon" > 🎮 </ span > Game</ a >
< a href = "/projects?tab={{ current_tab }}&type=software" class = "sidebar-link {% if project_type == 'software' %}active{% endif %}" >< span class = "icon" > 💻 </ span > Software</ a >
< a href = "/projects?tab={{ current_tab }}&type=mobile_app" class = "sidebar-link {% if project_type == 'mobile_app' %}active{% endif %}" >< span class = "icon" > 📱 </ span > Mobile App</ a >
< a href = "/projects?tab={{ current_tab }}&type=website" class = "sidebar-link {% if project_type == 'website' %}active{% endif %}" >< span class = "icon" > 🌐 </ span > Website</ a >
2026-05-10 07:08:12 +00:00
</ div >
</ div >
{% if user %}
2026-05-12 11:08:38 +00:00
< div class = "sidebar-section" >
< div class = "sidebar-heading" > My Projects</ div >
2026-05-12 13:07:34 +00:00
< a href = "/projects?user_uid={{ user['uid'] }}" class = "btn btn-secondary btn-sm full-width justify-center" >< span class = "icon" > 👤 </ span > View My Projects</ a >
2026-05-10 07:08:12 +00:00
</ div >
{% endif %}
</ aside >
< div class = "projects-main" >
< div class = "projects-header" >
< div >
2026-05-11 03:30:51 +00:00
< h1 > Projects</ h1 >
2026-05-10 07:08:12 +00:00
< span class = "subtitle" > Discover amazing projects from the DevPlace community</ span >
</ div >
< div class = "projects-count" > Showing {{ total_count }} of {{ total_count }} projects</ div >
</ div >
< div class = "projects-tabs" >
2026-05-16 01:10:55 +00:00
< a href = "/projects?tab=recent" class = "projects-tab {% if current_tab == 'recent' or not current_tab %}active{% endif %}" >< span class = "icon" > 🕐 </ span > Recently Released</ a >
< a href = "/projects?tab=popular" class = "projects-tab {% if current_tab == 'popular' %}active{% endif %}" >< span class = "icon" > 🔥 </ span > Most Popular</ a >
< a href = "/projects?tab=new" class = "projects-tab {% if current_tab == 'new' %}active{% endif %}" >< span class = "icon" > 🆕 </ span > New This Week</ a >
2026-05-10 07:08:12 +00:00
{% if user %}
2026-05-16 01:10:55 +00:00
< a href = "/projects?user_uid={{ user['uid'] }}" class = "projects-tab {% if request.query_params.get('user_uid') %}active{% endif %}" >< span class = "icon" > 👤 </ span > My Projects</ a >
2026-05-10 07:08:12 +00:00
{% endif %}
</ div >
< div class = "projects-grid" >
{% for project in projects %}
2026-05-22 23:50:31 +00:00
< div class = "project-card fade-in" data-href = "/projects/{{ project['slug'] or project['uid'] }}" >
2026-05-10 07:08:12 +00:00
< div class = "project-card-header" >
< h3 class = "project-card-title" > {{ project['title'] }}</ h3 >
2026-05-12 13:07:34 +00:00
< form method = "POST" action = "/votes/project/{{ project['uid'] }}" class = "inline-form" >
2026-05-10 22:41:41 +00:00
< input type = "hidden" name = "value" value = "1" >
< button type = "submit" class = "project-card-star" > ☆ </ button >
</ form >
2026-05-10 07:08:12 +00:00
</ div >
< div class = "project-card-meta" >
< span > By {{ project.get('author_name', 'Unknown') }}</ span >
{% if project.get('release_date') %}
< span > 📅 {{ project['release_date'] }}</ span >
{% endif %}
< span class = "project-status {% if project.get('status') == 'Released' %}released{% else %}dev{% endif %}" >
● {{ project.get('status', 'In Development') }}
</ span >
</ div >
2026-05-11 03:30:51 +00:00
< div class = "project-card-desc rendered-content" data-render > {{ project.get('description', '')[:200] }}</ div >
2026-05-10 07:08:12 +00:00
2026-05-12 13:07:34 +00:00
< div class = "flex-between" >
< span class = "badge badge-type" > {{ project.get('project_type', 'software').replace('_', ' ') }}</ span >
2026-05-10 07:08:12 +00:00
{% if project.get('platforms') %}
< div class = "project-card-platforms" >
{% for p in project['platforms'].split(',') %}
< span class = "platform-tag" > {{ p.strip() }}</ span >
{% endfor %}
</ div >
{% endif %}
</ div >
2026-05-22 23:50:31 +00:00
</ div >
2026-05-10 07:08:12 +00:00
{% else %}
2026-05-12 13:07:34 +00:00
< div class = "empty-state empty-state-full" > No projects found. Create one!</ div >
2026-05-10 07:08:12 +00:00
{% endfor %}
</ div >
</ div >
</ div >
2026-05-12 11:08:38 +00:00
{% if user %}
2026-05-12 13:07:34 +00:00
< button class = "feed-fab" id = "create-project-btn" title = "Add Project" data-modal = "create-project-modal" > +</ button >
2026-05-10 07:08:12 +00:00
2026-05-11 03:30:51 +00:00
< div class = "modal-overlay" id = "create-project-modal" >
2026-05-12 13:07:34 +00:00
< div class = "card modal-card" >
< div class = "modal-header" >
< h3 > Create Project</ h3 >
< button type = "button" class = "modal-close btn-ghost btn-icon modal-close-btn" > × </ button >
2026-05-10 07:08:12 +00:00
</ div >
< form method = "POST" action = "/projects/create" >
2026-05-12 13:07:34 +00:00
< div class = "auth-field auth-field-gap" >
2026-05-10 07:08:12 +00:00
< label for = "title" > Title</ label >
< input type = "text" id = "title" name = "title" required maxlength = "200" placeholder = "Project name" >
</ div >
2026-05-12 13:07:34 +00:00
< div class = "auth-field auth-field-gap" >
2026-05-10 07:08:12 +00:00
< label for = "description" > Description</ label >
2026-05-12 13:07:34 +00:00
< textarea id = "description" name = "description" required maxlength = "5000" placeholder = "Describe your project" class = "min-h-100" data-mention ></ textarea >
2026-05-10 07:08:12 +00:00
</ div >
2026-05-12 13:07:34 +00:00
< div class = "grid-2col" >
2026-05-10 07:08:12 +00:00
< div class = "auth-field" >
< label for = "release_date" > Release Date</ label >
< input type = "date" id = "release_date" name = "release_date" >
</ div >
< div class = "auth-field" >
< label for = "demo_date" > Demo Date</ label >
< input type = "date" id = "demo_date" name = "demo_date" >
</ div >
</ div >
2026-05-12 13:07:34 +00:00
< div class = "auth-field auth-field-gap" >
2026-05-10 07:08:12 +00:00
< label > Type</ label >
2026-05-12 13:07:34 +00:00
< div class = "flex-wrap-gap" >
2026-05-10 07:08:12 +00:00
{% for t in [('game', 'Game'), ('game_asset', 'Game Asset'), ('software', 'Software'), ('mobile_app', 'Mobile App'), ('website', 'Website')] %}
2026-05-12 13:07:34 +00:00
< label class = "topic-label" >
< input type = "radio" name = "project_type" value = "{{ t[0] }}" {% if t [ 0 ] == ' software ' %} checked {% endif %} class = "topic-radio" >
2026-05-10 07:08:12 +00:00
{{ t[1] }}
</ label >
{% endfor %}
</ div >
</ div >
2026-05-12 13:07:34 +00:00
< div class = "auth-field auth-field-gap" >
2026-05-10 07:08:12 +00:00
< label > Status</ label >
2026-05-12 13:07:34 +00:00
< div class = "flex-wrap-gap" >
< label class = "topic-label" >
< input type = "radio" name = "status" value = "In Development" checked class = "topic-radio" > In Development
2026-05-10 07:08:12 +00:00
</ label >
2026-05-12 13:07:34 +00:00
< label class = "topic-label" >
< input type = "radio" name = "status" value = "Released" class = "topic-radio" > Released
2026-05-10 07:08:12 +00:00
</ label >
</ div >
</ div >
2026-05-12 13:07:34 +00:00
< div class = "auth-field auth-field-gap-last" >
2026-05-10 07:08:12 +00:00
< label > Platforms</ label >
2026-05-12 13:07:34 +00:00
< div id = "platforms-tags" class = "flex-wrap-gap-bottom" ></ div >
< input type = "text" id = "platforms-input" class = "input-sm" placeholder = "Add platform (press Enter)" >
2026-05-10 07:08:12 +00:00
< input type = "hidden" id = "platforms" name = "platforms" value = "" >
2026-05-12 13:07:34 +00:00
< div class = "platform-presets-wrap" >
2026-05-10 07:08:12 +00:00
{% for p in ['PC', 'Windows', 'Mac', 'Linux', 'iOS', 'Android', 'Web', 'Console'] %}
2026-05-12 13:07:34 +00:00
< button type = "button" class = "platform-preset" data-platform = "{{ p }}" > {{ p }}</ button >
2026-05-10 07:08:12 +00:00
{% endfor %}
</ div >
</ div >
2026-05-12 13:07:34 +00:00
{% include "_attachment_form.html" %}
< div class = "modal-footer" >
2026-05-10 07:08:12 +00:00
< button type = "button" class = "modal-close btn btn-secondary" > Cancel</ button >
< button type = "submit" class = "btn btn-primary" > Create Project</ button >
</ div >
</ form >
</ div >
</ div >
2026-05-12 11:08:38 +00:00
{% endif %}
2026-05-10 07:08:12 +00:00
{% endblock %}