Compare commits

..

6 Commits

Author SHA1 Message Date
Flatlogic Bot
c3c95bde7c Edit core/apps.py via Editor 2025-12-02 16:16:55 +00:00
Flatlogic Bot
ba57f4eeba Edit core/apps.py via Editor 2025-12-02 16:16:31 +00:00
Flatlogic Bot
06afc55e42 Auto commit: 2025-12-02T16:15:04.725Z 2025-12-02 16:15:04 +00:00
Flatlogic Bot
b0afe7cbe9 Auto commit: 2025-12-02T16:09:33.054Z 2025-12-02 16:09:33 +00:00
Flatlogic Bot
4647314b9d Auto commit: 2025-12-02T16:01:28.239Z 2025-12-02 16:01:28 +00:00
Flatlogic Bot
82cd023d5e Auto commit: 2025-12-02T15:53:31.748Z 2025-12-02 15:53:31 +00:00
28 changed files with 366 additions and 169 deletions

Binary file not shown.

Binary file not shown.

View File

@ -180,3 +180,6 @@ if EMAIL_USE_SSL:
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'home'

View File

@ -18,9 +18,12 @@ from django.contrib import admin
from django.urls import include, path from django.urls import include, path
from django.conf import settings from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from core import views as core_views
urlpatterns = [ urlpatterns = [
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("accounts/signup/", core_views.signup, name="signup"),
path("accounts/", include("django.contrib.auth.urls")),
path("", include("core.urls")), path("", include("core.urls")),
] ]

Binary file not shown.

23
core/forms.py Normal file
View File

@ -0,0 +1,23 @@
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import Article, Reflection
class SignUpForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
fields = ("username", "email")
def __init__(self, *args, **kwargs):
super(SignUpForm, self).__init__(*args, **kwargs)
self.fields['email'].required = True
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ('title', 'content')
class ReflectionForm(forms.ModelForm):
class Meta:
model = Reflection
fields = ('answer',)

View File

@ -0,0 +1,27 @@
# Generated by Django 5.2.7 on 2025-12-02 15:53
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Article',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('content', models.TextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -0,0 +1,26 @@
# Generated by Django 5.2.7 on 2025-12-02 15:59
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Reflection',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('question', models.TextField()),
('answer', models.TextField(blank=True, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 5.2.7 on 2025-12-02 16:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0002_reflection'),
]
operations = [
migrations.AddField(
model_name='reflection',
name='feedback',
field=models.TextField(blank=True, null=True),
),
]

View File

@ -1,3 +1,21 @@
from django.db import models from django.db import models
from django.contrib.auth.models import User
# Create your models here. class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Reflection(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
question = models.TextField()
answer = models.TextField(blank=True, null=True)
feedback = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"Reflection for {self.user.username} at {self.created_at}"

View File

@ -14,12 +14,39 @@
<meta property="twitter:image" content="{{ project_image_url }}"> <meta property="twitter:image" content="{{ project_image_url }}">
{% endif %} {% endif %}
{% load static %} {% load static %}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}"> <link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
{% block head %}{% endblock %} {% block head %}{% endblock %}
</head> </head>
<body> <body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="{% url 'home' %}">Home</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'logout' %}">Logout</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'signup' %}">Sign Up</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<div class="container">
{% block content %}{% endblock %} {% block content %}{% endblock %}
</div>
</body> </body>
</html> </html>

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% block content %}
<h2>Articles</h2>
<ul>
{% for article in articles %}
<li><a href="{% url 'article_detail' pk=article.pk %}">{{ article.title }}</a></li>
{% endfor %}
</ul>
<a href="{% url 'article_create' %}">New Article</a>
{% endblock %}

View File

@ -1,145 +1,16 @@
{% extends "base.html" %} {% extends 'base.html' %}
{% load static %}
{% block title %}{{ project_name }}{% endblock %}
{% block head %}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
inset: 0;
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'><path d='M-10 10L110 10M10 -10L10 110' stroke-width='1' stroke='rgba(255,255,255,0.05)'/></svg>");
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% {
background-position: 0% 0%;
}
100% {
background-position: 100% 100%;
}
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2.5rem 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
}
h1 {
font-size: clamp(2.2rem, 3vw + 1.2rem, 3.2rem);
font-weight: 700;
margin: 0 0 1.2rem;
letter-spacing: -0.02em;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
opacity: 0.92;
}
.loader {
margin: 1.5rem auto;
width: 56px;
height: 56px;
border: 4px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.runtime code {
background: rgba(0, 0, 0, 0.25);
padding: 0.15rem 0.45rem;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
footer {
position: absolute;
bottom: 1rem;
width: 100%;
text-align: center;
font-size: 0.85rem;
opacity: 0.75;
}
</style>
{% endblock %}
{% block content %} {% block content %}
<main> <div class="hero-section">
<div class="card"> <div class="container">
<h1>Analyzing your requirements and generating your app…</h1> <div class="row">
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes"> <div class="col-lg-8 mx-auto text-center">
<span class="sr-only">Loading…</span> <h1 class="display-4">Reflect and Grow</h1>
<p class="lead">Your personal AI-powered self-reflection companion. Understand your year, set your goals, and unlock your potential.</p>
<a href="{% url 'signup' %}" class="btn btn-primary btn-lg">Get Started</a>
</div>
</div>
</div> </div>
<p class="hint">AppWizzy AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will refresh automatically as the plan is implemented.</p>
<p class="runtime">
Runtime: Django <code>{{ django_version }}</code> · Python <code>{{ python_version }}</code>
— UTC <code>{{ current_time|date:"Y-m-d H:i:s" }}</code>
</p>
</div> </div>
</main>
<footer>
Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC)
</footer>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,42 @@
{% extends "base.html" %}
{% block content %}
<div class="container">
<h1 class="my-4">AI Reflection</h1>
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-body">
<h5 class="card-title">This week's question:</h5>
<p class="card-text">{{ question }}</p>
<form method="post">
{% csrf_token %}
<input type="hidden" name="question" value="{{ question }}">
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Previous Reflections</h5>
<ul class="list-group list-group-flush">
{% for reflection in reflections %}
<li class="list-group-item">
<strong>{{ reflection.question }}</strong><br>
{{ reflection.answer }}<br>
{% if reflection.feedback %}
<strong>Feedback:</strong><br>
<p class="text-muted">{{ reflection.feedback }}</p>
{% endif %}
<small class="text-muted">{{ reflection.created_at|date:"F d, Y" }}</small>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}

View File

@ -0,0 +1,10 @@
{% extends 'base.html' %}
{% block content %}
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign up</button>
</form>
{% endblock %}

View File

@ -1,7 +1,8 @@
from django.urls import path from django.urls import path
from .views import home from . import views
urlpatterns = [ urlpatterns = [
path("", home, name="home"), path("", views.home, name="home"),
path('reflection/', views.reflection_view, name='reflection'),
] ]

View File

@ -1,10 +1,16 @@
import os import os
import platform import platform
import json
from django import get_version as django_version from django import get_version as django_version
from django.shortcuts import render from django.contrib.auth import login
from django.shortcuts import redirect, render, get_object_or_404
from django.utils import timezone from django.utils import timezone
from django.contrib.auth.decorators import login_required
from .models import Article, Reflection
from .forms import SignUpForm, ArticleForm, ReflectionForm
from ai.local_ai_api import LocalAIApi
def home(request): def home(request):
"""Render the landing screen with loader and environment details.""" """Render the landing screen with loader and environment details."""
@ -23,3 +29,81 @@ def home(request):
"project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""),
} }
return render(request, "core/index.html", context) return render(request, "core/index.html", context)
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'registration/signup.html', {'form': form})
@login_required
def article_list(request):
articles = Article.objects.filter(author=request.user)
return render(request, 'core/article_list.html', {'articles': articles})
@login_required
def article_detail(request, pk):
article = get_object_or_404(Article, pk=pk, author=request.user)
return render(request, 'core/article_detail.html', {'article': article})
@login_required
def article_create(request):
if request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
article = form.save(commit=False)
article.author = request.user
article.save()
return redirect('article_detail', pk=article.pk)
else:
form = ArticleForm()
return render(request, 'core/article_form.html', {'form': form})
@login_required
def reflection_view(request):
# AI-generated question
response = LocalAIApi.create_response({
"input": [
{"role": "system", "content": "You are a helpful assistant. Your task is to ask a single, short, thought-provoking question to help a user reflect on their week. The question should be suitable for a professional in the tech industry. The question should be no more than 20 words."},
{"role": "user", "content": "Ask me a question."},
],
})
if response.get("success"):
question = LocalAIApi.extract_text(response)
else:
question = "What is your biggest challenge this week?" # Fallback question
if request.method == 'POST':
form = ReflectionForm(request.POST)
if form.is_valid():
reflection = form.save(commit=False)
reflection.user = request.user
reflection.question = request.POST.get('question') # Get question from hidden input
# AI-generated feedback
feedback_response = LocalAIApi.create_response({
"input": [
{"role": "system", "content": "You are a helpful assistant. Your task is to provide brief, encouraging, and constructive feedback on a user\'s reflection. The feedback should be no more than 50 words."},
{"role": "user", "content": f"The user was asked: '{reflection.question}' and they responded: '{reflection.answer}'. Please provide some feedback."},
],
})
if feedback_response.get("success"):
reflection.feedback = LocalAIApi.extract_text(feedback_response)
else:
reflection.feedback = "Thank you for your reflection." # Fallback feedback
reflection.save()
return redirect('reflection')
else:
form = ReflectionForm()
reflections = Reflection.objects.filter(user=request.user).order_by('-created_at')
return render(request, 'core/reflection.html', {'form': form, 'question': question, 'reflections': reflections})

View File

@ -1,4 +1,24 @@
/* Custom styles for the application */
body { body {
font-family: system-ui, -apple-system, sans-serif; font-family: 'Roboto', sans-serif;
background-color: #f0f0f0;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Poppins', sans-serif;
}
.hero-section {
background: linear-gradient(45deg, #1a1a2e, #16213e);
color: #ffffff;
padding: 100px 0;
}
.btn-primary {
background-color: #e94560;
border-color: #e94560;
}
.btn-primary:hover {
background-color: #d43d51;
border-color: #d43d51;
} }

View File

@ -1,21 +1,24 @@
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
body { body {
margin: 0; font-family: 'Roboto', sans-serif;
font-family: 'Inter', sans-serif; background-color: #f0f0f0;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); }
color: var(--text-color);
display: flex; h1, h2, h3, h4, h5, h6 {
justify-content: center; font-family: 'Poppins', sans-serif;
align-items: center; }
min-height: 100vh;
text-align: center; .hero-section {
overflow: hidden; background: linear-gradient(45deg, #1a1a2e, #16213e);
position: relative; color: #ffffff;
padding: 100px 0;
}
.btn-primary {
background-color: #e94560;
border-color: #e94560;
}
.btn-primary:hover {
background-color: #d43d51;
border-color: #d43d51;
} }