diff --git a/img/line-2.svg b/brainwave/__init__.py
similarity index 100%
rename from img/line-2.svg
rename to brainwave/__init__.py
diff --git a/brainwave/__pycache__/__init__.cpython-38.pyc b/brainwave/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..d773277
Binary files /dev/null and b/brainwave/__pycache__/__init__.cpython-38.pyc differ
diff --git a/brainwave/__pycache__/settings.cpython-38.pyc b/brainwave/__pycache__/settings.cpython-38.pyc
new file mode 100644
index 0000000..b089c41
Binary files /dev/null and b/brainwave/__pycache__/settings.cpython-38.pyc differ
diff --git a/brainwave/__pycache__/urls.cpython-38.pyc b/brainwave/__pycache__/urls.cpython-38.pyc
new file mode 100644
index 0000000..fc2d581
Binary files /dev/null and b/brainwave/__pycache__/urls.cpython-38.pyc differ
diff --git a/brainwave/__pycache__/wsgi.cpython-38.pyc b/brainwave/__pycache__/wsgi.cpython-38.pyc
new file mode 100644
index 0000000..d975e06
Binary files /dev/null and b/brainwave/__pycache__/wsgi.cpython-38.pyc differ
diff --git a/brainwave/asgi.py b/brainwave/asgi.py
new file mode 100644
index 0000000..23af5fe
--- /dev/null
+++ b/brainwave/asgi.py
@@ -0,0 +1,16 @@
+"""
+ASGI config for brainwave project.
+
+It exposes the ASGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'brainwave.settings')
+
+application = get_asgi_application()
diff --git a/brainwave/settings.py b/brainwave/settings.py
new file mode 100644
index 0000000..8ecb8a1
--- /dev/null
+++ b/brainwave/settings.py
@@ -0,0 +1,125 @@
+from pathlib import Path
+import os
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'django-insecure-_*7_%im@0@58xl)8q^5cibhb6p^bn+788c$-_)lh*-kuf@2k(4'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+LOGIN_URL = '/login/'
+LOGIN_REDIRECT_URL = '/brainwave/'
+LOGOUT_REDIRECT_URL = '/brainwave/'
+
+
+# Application definition
+
+INSTALLED_APPS = [
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+ 'core',
+ 'item',
+ 'post',
+]
+
+MIDDLEWARE = [
+ 'django.middleware.security.SecurityMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'brainwave.urls'
+
+STATICFILES_DIRS = [
+ os.path.join(BASE_DIR, 'CORE', 'STATIC'),
+]
+
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+]
+
+WSGI_APPLICATION = 'brainwave.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': BASE_DIR / 'db.sqlite3',
+ }
+}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+ {
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+ },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/4.2/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/4.2/howto/static-files/
+
+STATIC_URL = '/static/'
+MEDIA_URL = 'media/'
+MEDIA_ROOT = BASE_DIR / 'media'
+
+# Default primary key field type
+# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
diff --git a/brainwave/urls.py b/brainwave/urls.py
new file mode 100644
index 0000000..a067f86
--- /dev/null
+++ b/brainwave/urls.py
@@ -0,0 +1,12 @@
+from django.conf import settings
+from django.conf.urls.static import static
+from django.contrib import admin
+from django.urls import path, include
+
+urlpatterns = [
+ path('', include('core.urls')),
+ path('items/', include('item.urls')),
+ path('post/', include('post.urls')),
+ path('admin/', admin.site.urls),
+] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+
diff --git a/brainwave/wsgi.py b/brainwave/wsgi.py
new file mode 100644
index 0000000..97cd9f1
--- /dev/null
+++ b/brainwave/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for brainwave project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'brainwave.settings')
+
+application = get_wsgi_application()
diff --git a/core/__init__.py b/core/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/core/__pycache__/__init__.cpython-38.pyc b/core/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..c3b95f0
Binary files /dev/null and b/core/__pycache__/__init__.cpython-38.pyc differ
diff --git a/core/__pycache__/admin.cpython-38.pyc b/core/__pycache__/admin.cpython-38.pyc
new file mode 100644
index 0000000..4aac12b
Binary files /dev/null and b/core/__pycache__/admin.cpython-38.pyc differ
diff --git a/core/__pycache__/apps.cpython-38.pyc b/core/__pycache__/apps.cpython-38.pyc
new file mode 100644
index 0000000..f459264
Binary files /dev/null and b/core/__pycache__/apps.cpython-38.pyc differ
diff --git a/core/__pycache__/forms.cpython-38.pyc b/core/__pycache__/forms.cpython-38.pyc
new file mode 100644
index 0000000..b2d1246
Binary files /dev/null and b/core/__pycache__/forms.cpython-38.pyc differ
diff --git a/core/__pycache__/models.cpython-38.pyc b/core/__pycache__/models.cpython-38.pyc
new file mode 100644
index 0000000..2f8ba6d
Binary files /dev/null and b/core/__pycache__/models.cpython-38.pyc differ
diff --git a/core/__pycache__/urls.cpython-38.pyc b/core/__pycache__/urls.cpython-38.pyc
new file mode 100644
index 0000000..ff61e11
Binary files /dev/null and b/core/__pycache__/urls.cpython-38.pyc differ
diff --git a/core/__pycache__/views.cpython-38.pyc b/core/__pycache__/views.cpython-38.pyc
new file mode 100644
index 0000000..c13c847
Binary files /dev/null and b/core/__pycache__/views.cpython-38.pyc differ
diff --git a/core/admin.py b/core/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/core/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/core/apps.py b/core/apps.py
new file mode 100644
index 0000000..8115ae6
--- /dev/null
+++ b/core/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class CoreConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'core'
diff --git a/core/forms.py b/core/forms.py
new file mode 100644
index 0000000..29a7245
--- /dev/null
+++ b/core/forms.py
@@ -0,0 +1,40 @@
+from django import forms
+from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
+from django.contrib.auth.models import User
+
+
+class LoginForm(AuthenticationForm):
+ username = forms.CharField(widget=forms.TextInput(attrs={
+ 'placeholder': 'Nome de Usuário',
+ 'class': 'w-full py-4 px-6 rounded-xl'
+ }))
+
+ password = forms.CharField(widget=forms.PasswordInput(attrs={
+ 'placeholder': 'Senha',
+ 'class': 'w-full py-4 px-6 rounded-xl'
+ }))
+
+class SignupForm(UserCreationForm):
+ class Meta:
+ model = User
+ fields = ('username', 'email', 'password1', 'password2')
+
+ username = forms.CharField(widget=forms.TextInput(attrs={
+ 'placeholder': 'Nome de Usuário',
+ 'class': 'w-full py-4 px-6 rounded-xl'
+ }))
+
+ email = forms.CharField(widget=forms.EmailInput(attrs={
+ 'placeholder': 'E-mail',
+ 'class': 'w-full py-4 px-6 rounded-xl'
+ }))
+
+ password1 = forms.CharField(widget=forms.PasswordInput(attrs={
+ 'placeholder': 'Senha',
+ 'class': 'w-full py-4 px-6 rounded-xl'
+ }))
+
+ password2 = forms.CharField(widget=forms.PasswordInput(attrs={
+ 'placeholder': 'Confirme senha',
+ 'class': 'w-full py-4 px-6 rounded-xl'
+ }))
\ No newline at end of file
diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py
new file mode 100644
index 0000000..d8b2f59
--- /dev/null
+++ b/core/migrations/0001_initial.py
@@ -0,0 +1,32 @@
+# Generated by Django 4.2.7 on 2023-11-27 05:41
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Thread',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=200)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Post',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('content', models.TextField()),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('thread', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.thread')),
+ ],
+ ),
+ ]
diff --git a/core/migrations/0002_delete_post_delete_thread.py b/core/migrations/0002_delete_post_delete_thread.py
new file mode 100644
index 0000000..f43c543
--- /dev/null
+++ b/core/migrations/0002_delete_post_delete_thread.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.2.7 on 2023-11-28 08:30
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.DeleteModel(
+ name='Post',
+ ),
+ migrations.DeleteModel(
+ name='Thread',
+ ),
+ ]
diff --git a/core/migrations/__init__.py b/core/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/core/migrations/__pycache__/0001_initial.cpython-38.pyc b/core/migrations/__pycache__/0001_initial.cpython-38.pyc
new file mode 100644
index 0000000..a69d2ae
Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-38.pyc differ
diff --git a/core/migrations/__pycache__/0002_delete_post_delete_thread.cpython-38.pyc b/core/migrations/__pycache__/0002_delete_post_delete_thread.cpython-38.pyc
new file mode 100644
index 0000000..b13515e
Binary files /dev/null and b/core/migrations/__pycache__/0002_delete_post_delete_thread.cpython-38.pyc differ
diff --git a/core/migrations/__pycache__/__init__.cpython-38.pyc b/core/migrations/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..16294fb
Binary files /dev/null and b/core/migrations/__pycache__/__init__.cpython-38.pyc differ
diff --git a/core/models.py b/core/models.py
new file mode 100644
index 0000000..b096caa
--- /dev/null
+++ b/core/models.py
@@ -0,0 +1,4 @@
+from django.db import models
+
+# Create your models here.
+
diff --git a/css/create_post.css b/core/static/css/create_post.css
similarity index 90%
rename from css/create_post.css
rename to core/static/css/create_post.css
index b4056df..35bd808 100644
--- a/css/create_post.css
+++ b/core/static/css/create_post.css
@@ -17,7 +17,7 @@
padding: 20px 25px;
border-radius: 79px;
- border: 0px;
+ border: 2px solid var(--color-black);
background-color: var(--color-blueviolet);
}
@@ -34,7 +34,7 @@
color: white;
border-radius: 79px;
- border: 0px;
+ border: 2px solid var(--color-black);
background-color: var(--color-blueviolet);
}
diff --git a/core/static/css/global.css b/core/static/css/global.css
new file mode 100644
index 0000000..0fd7250
--- /dev/null
+++ b/core/static/css/global.css
@@ -0,0 +1,37 @@
+:root {
+ /* fonts */
+ --font-inter: Inter;
+ --font-inherit: inherit;
+ --font-arial: Arial;
+
+ /* font sizes */
+ --font-size-9xl: 28px;
+ --font-size-10xl: 29px;
+ --font-size-13xl: 32px;
+ --font-size-17xl: 36px;
+ --font-size-29xl: 48px;
+ --font-size-45xl: 64px;
+
+ /* Colors */
+ --color-gray-200: #1e1e1e;
+ --color-gray-100: #1f132f;
+ --color-gray-300: #0d0d0d;
+ --color-gray-400: #13001e;
+ --color-white: #fff;
+ --color-black: #000;
+ --color-blueviolet: #6b00bf;
+ --color-fuchsia: #ee00ff;
+
+ /* Gaps */
+ --gap-6xl: 25px;
+
+ /* Paddings */
+ --padding-18xl: 37px;
+ --padding-20xl: 39px;
+
+ /* Border radiuses */
+ --br-41xl: 60px;
+ --br-60xl: 79px;
+ --br-lgi: 19px;
+ --br-3xs: 10px;
+ }
\ No newline at end of file
diff --git a/css/index.css b/core/static/css/index.css
similarity index 92%
rename from css/index.css
rename to core/static/css/index.css
index 1c7c808..bf926a8 100644
--- a/css/index.css
+++ b/core/static/css/index.css
@@ -122,8 +122,6 @@ body {
font-size: var(--font-size-13xl);
justify-self: center;
align-self: center;
-
-
}
.login_icon{
@@ -233,3 +231,27 @@ body {
appearance: none;
background-color: inherit;
}
+
+.dropdown {
+ text-decoration: none;
+ color: inherit;
+}
+
+.dropdown-menu{
+ width: 150px;
+ position: absolute;
+ box-shadow: 0 0 5px #ee00ff;
+ display: none;
+ border-radius: 5px;
+ background-color: #0d0c0c;
+}
+
+.dropdown-menu a{
+ display: block;
+ color: #ee00ff;
+}
+
+.dropdown:hover .dropdown-menu{
+ display: block;
+}
+
diff --git a/css/login.css b/core/static/css/login.css
similarity index 58%
rename from css/login.css
rename to core/static/css/login.css
index 3c1dc5a..3069b32 100644
--- a/css/login.css
+++ b/core/static/css/login.css
@@ -1,4 +1,3 @@
-
.cadastro{
width: 50%;
display:flex;
@@ -50,8 +49,48 @@ form button{
color: white;
}
+.error-container {
+ background-color: #0d0c0c;
+ color:#ff0066;
+ padding: 1rem;
+ border-radius: 0.25rem;
+ margin-bottom: 1rem;
+}
+
.login{
width: 50%;
display:flex;
justify-content: center;
-}
\ No newline at end of file
+}
+
+/* Estilo para o pop-up */
+.popup {
+ display: none;
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ z-index: 1;
+}
+
+.popup-content {
+ background-color: #f9f9f9;
+ padding: 20px;
+ border: 1px solid #888;
+ width: 300px;
+}
+
+.close {
+ color: #aaa;
+ float: right;
+ font-size: 28px;
+ font-weight: bold;
+}
+
+.close:hover,
+.close:focus {
+ color: black;
+ text-decoration: none;
+ cursor: pointer;
+}
+
diff --git a/core/static/css/post.css b/core/static/css/post.css
new file mode 100644
index 0000000..67df270
--- /dev/null
+++ b/core/static/css/post.css
@@ -0,0 +1,68 @@
+.novo_post {
+ display:flex;
+ align-items: center;
+ flex-direction: column;
+
+ height: 100%;
+
+ gap: 28px;
+}
+
+.novo_post input{
+ font-size: 32px;
+ color: white;
+
+ width: 577px;
+
+ padding: 20px 25px;
+
+ border-radius: 79px;
+ border: 0px;
+ background-color: var(--color-blueviolet);
+}
+
+.novo_post textarea {
+ resize: none;
+
+ width: 1050px;
+ height: 200px;
+
+ padding: 20px 50px;
+
+ font-size: 32px;
+ line-height: 40px;
+ color: white;
+
+ border-radius: 79px;
+ border: 2px solid var(--color-black);
+ background-color: var(--color-blueviolet);
+}
+
+
+.novo_post button{
+ border: none;
+ appearance: none;
+ background-color: inherit;
+}
+
+.post_comment{
+ width: 1145px;
+ height: auto;
+ padding: 15px 40px;
+
+ border-radius: var(--br-41xl);
+ background-color: var(--color-blueviolet);
+ border: 2px solid var(--color-black);
+ box-sizing: border-box;
+ color: white;
+ font-family: var(--font-arial);
+ font-size: var(--font-size-13xl);
+}
+
+.post_comment .titulo{
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 50px;
+ margin-bottom: 50px;
+}
\ No newline at end of file
diff --git a/core/static/images/bin.png b/core/static/images/bin.png
new file mode 100644
index 0000000..d362bf3
Binary files /dev/null and b/core/static/images/bin.png differ
diff --git a/img/brain-11@2x.png b/core/static/images/brain-11@2x.png
similarity index 100%
rename from img/brain-11@2x.png
rename to core/static/images/brain-11@2x.png
diff --git a/img/brain-1@2x.png b/core/static/images/brain-1@2x.png
similarity index 100%
rename from img/brain-1@2x.png
rename to core/static/images/brain-1@2x.png
diff --git a/img/enviar-1@2x.png b/core/static/images/enviar-1@2x.png
similarity index 100%
rename from img/enviar-1@2x.png
rename to core/static/images/enviar-1@2x.png
diff --git a/img/home@2x.png b/core/static/images/home@2x.png
similarity index 100%
rename from img/home@2x.png
rename to core/static/images/home@2x.png
diff --git a/core/static/images/line-2.svg b/core/static/images/line-2.svg
new file mode 100644
index 0000000..e69de29
diff --git a/img/logo@2x.png b/core/static/images/logo@2x.png
similarity index 100%
rename from img/logo@2x.png
rename to core/static/images/logo@2x.png
diff --git a/img/mascote@2x.png b/core/static/images/mascote@2x.png
similarity index 100%
rename from img/mascote@2x.png
rename to core/static/images/mascote@2x.png
diff --git a/img/onda-roxa@2x.png b/core/static/images/onda-roxa@2x.png
similarity index 100%
rename from img/onda-roxa@2x.png
rename to core/static/images/onda-roxa@2x.png
diff --git a/img/pessoa@2x.png b/core/static/images/pessoa@2x.png
similarity index 100%
rename from img/pessoa@2x.png
rename to core/static/images/pessoa@2x.png
diff --git a/img/resposta-1-3@2x.png b/core/static/images/resposta-1-3@2x.png
similarity index 100%
rename from img/resposta-1-3@2x.png
rename to core/static/images/resposta-1-3@2x.png
diff --git a/img/speechbubble-1-1@2x.png b/core/static/images/speechbubble-1-1@2x.png
similarity index 100%
rename from img/speechbubble-1-1@2x.png
rename to core/static/images/speechbubble-1-1@2x.png
diff --git a/core/templates/core/base.html b/core/templates/core/base.html
new file mode 100644
index 0000000..e34d119
--- /dev/null
+++ b/core/templates/core/base.html
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+ {% block title %}{% endblock %} | Puddle
+
+
+
+
+ Puddle
+
+
+
+
+
+ {% block content %}
+ {% endblock %}
+
+
+
+
+
\ No newline at end of file
diff --git a/core/templates/core/brainwave.html b/core/templates/core/brainwave.html
new file mode 100644
index 0000000..ec9bffb
--- /dev/null
+++ b/core/templates/core/brainwave.html
@@ -0,0 +1,119 @@
+{% load static %}
+
+
+
+
+
+
+
+
+
+
+
+ {% block title %}Página Inicial | Brainwave{% endblock %}
+
+
+
+
+
+
+
+
+
“Conectando mentes acadêmicas” - GRAN
+
Brainwave
+
Network
+
+
+
+
+
+
+
+
+
+ {% for post in posts_by_date %}
+
+
+
{{ post.texto }}
+
+
+
+
+
+
+
+ {% endfor %}
+
+
+
+
+
+
+
+
diff --git a/core/templates/core/index.html b/core/templates/core/index.html
new file mode 100644
index 0000000..51c7cfe
--- /dev/null
+++ b/core/templates/core/index.html
@@ -0,0 +1,43 @@
+{% extends 'core/base.html' %}
+
+{% block title %}Welcome{% endblock %}
+
+{% block content %}
+
+
Newest items
+
+
+ {% for item in items %}
+
+ {% endfor %}
+
+
+
+
+
Categories
+
+
+ {% for category in categories %}
+
+ {% endfor %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/core/templates/core/login.html b/core/templates/core/login.html
new file mode 100644
index 0000000..e422f05
--- /dev/null
+++ b/core/templates/core/login.html
@@ -0,0 +1,91 @@
+{% load static %}
+
+
+
+
+
+
+
+
+
+
+
+ {% block title %}Login | Brainwave{% endblock %}
+
+
+
+
+
+
+
+
+
+
“Conectando mentes acadêmicas” - GRAN
+
Brainwave
+
Network
+
+
+
+
+
+
+
+
+
+
diff --git a/core/templates/core/register.html b/core/templates/core/register.html
new file mode 100644
index 0000000..dfdad8a
--- /dev/null
+++ b/core/templates/core/register.html
@@ -0,0 +1,93 @@
+{% load static %}
+
+
+
+
+
+
+
+
+
+
+
+ {% block title %}Cadastro | Brainwave{% endblock %}
+
+
+
+
+
+
+
+
+
+
“Conectando mentes acadêmicas” - GRAN
+
Brainwave
+
Network
+
+
+
+
+
+
+
+
+
+
diff --git a/core/tests.py b/core/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/core/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/core/urls.py b/core/urls.py
new file mode 100644
index 0000000..1b2be10
--- /dev/null
+++ b/core/urls.py
@@ -0,0 +1,18 @@
+from django.contrib.auth import views as auth_views
+from django.urls import path
+
+from . import views
+from .views import logout_view, delete_account
+from .forms import LoginForm
+
+app_name = 'core'
+
+urlpatterns = [
+ path('', views.index, name='index'),
+
+ path('register/', views.signup, name='register'),
+ path('login/', auth_views.LoginView.as_view(template_name='core/login.html', authentication_form=LoginForm), name='login'),
+ path('logout/', logout_view, name='logout'),
+ path('delete/', delete_account, name='delete'),
+ path('brainwave/', views.brainwave, name='brainwave'),
+]
\ No newline at end of file
diff --git a/core/views.py b/core/views.py
new file mode 100644
index 0000000..79055c1
--- /dev/null
+++ b/core/views.py
@@ -0,0 +1,55 @@
+from django.shortcuts import render, redirect
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth import logout, authenticate, login
+from django.contrib.auth.forms import AuthenticationForm
+from item.models import Category, Item
+from django.db.models import Count
+from post.models import Post
+from .forms import SignupForm, LoginForm
+
+def contact(request):
+ return render(request, 'core/contact.html')
+
+def brainwave(request):
+ # Obtenha os posts ordenados pela contagem de curtidas (do maior para o menor)
+ posts_by_likes = Post.objects.annotate(likes_count=Count('likes')).order_by('-likes_count')
+
+ # Obtenha os posts ordenados pela data de criação (do mais recente para o mais antigo)
+ posts_by_date = Post.objects.all().order_by('-created_at')
+
+ # Renderize o template 'brainwave.html' com as duas listas de posts
+ return render(request, 'core/brainwave.html', {'posts_by_likes': posts_by_likes, 'posts_by_date': posts_by_date})
+
+def index(request):
+ # Obtenha os posts ordenados pela contagem de curtidas (do maior para o menor)
+ posts_by_likes = Post.objects.annotate(likes_count=Count('likes')).order_by('-likes_count')
+
+ # Obtenha os posts ordenados pela data de criação (do mais recente para o mais antigo)
+ posts_by_date = Post.objects.all().order_by('-created_at')
+
+ # Renderize o template 'brainwave.html' com as duas listas de posts
+ return render(request, 'core/brainwave.html', {'posts_by_likes': posts_by_likes, 'posts_by_date': posts_by_date})
+
+def signup(request):
+ if request.method == 'POST':
+ form = SignupForm(request.POST)
+
+ if form.is_valid():
+ form.save()
+ return redirect('core:login')
+
+ else:
+ form = SignupForm()
+
+ return render(request, 'core/register.html', {'form': form})
+
+def logout_view(request):
+ logout(request)
+ return redirect('core:brainwave')
+
+@login_required
+def delete_account(request):
+ # Excluir o usuário e desconectar
+ request.user.delete()
+ logout(request)
+ return redirect('core:brainwave')
\ No newline at end of file
diff --git a/css/global.css b/css/global.css
deleted file mode 100644
index d1b1ea2..0000000
--- a/css/global.css
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-:root {
- /* fonts */
- --font-inter: Inter;
- --font-inherit: inherit;
- --font-arial: Arial;
-
- /* font sizes */
- --font-size-9xl: 28px;
- --font-size-10xl: 29px;
- --font-size-13xl: 32px;
- --font-size-17xl: 36px;
- --font-size-29xl: 48px;
- --font-size-45xl: 64px;
-
- /* Colors */
- --color-gray-200: #1e1e1e;
- --color-gray-100: #1f132f;
- --color-gray-300: #0d0d0d;
- --color-gray-400: #13001e;
- --color-white: #fff;
- --color-black: #000;
- --color-blueviolet: #6b00bf;
- --color-fuchsia: #ee00ff;
-
- /* Gaps */
- --gap-6xl: 25px;
-
- /* Paddings */
- --padding-18xl: 37px;
- --padding-20xl: 39px;
-
- /* Border radiuses */
- --br-41xl: 60px;
- --br-60xl: 79px;
- --br-lgi: 19px;
- --br-3xs: 10px;
-}
diff --git a/db.sqlite3 b/db.sqlite3
new file mode 100644
index 0000000..87b049f
Binary files /dev/null and b/db.sqlite3 differ
diff --git a/index.html b/index.html
deleted file mode 100644
index 49b9cac..0000000
--- a/index.html
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
“Conectando mentes acadêmicas” - GRAN
-
Brainwave
-
Network
-
-
-
-
-
-
-
-
-
-
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
-
-
5
-
-
-
-
-
-
-
-
-
-
-
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.
-
-
3
-
-
-
-
-
-
-
-
-
-
-
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
-
-
1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/item/__init__.py b/item/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/item/__pycache__/__init__.cpython-38.pyc b/item/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..53f7689
Binary files /dev/null and b/item/__pycache__/__init__.cpython-38.pyc differ
diff --git a/item/__pycache__/admin.cpython-38.pyc b/item/__pycache__/admin.cpython-38.pyc
new file mode 100644
index 0000000..4182bf6
Binary files /dev/null and b/item/__pycache__/admin.cpython-38.pyc differ
diff --git a/item/__pycache__/apps.cpython-38.pyc b/item/__pycache__/apps.cpython-38.pyc
new file mode 100644
index 0000000..1e49298
Binary files /dev/null and b/item/__pycache__/apps.cpython-38.pyc differ
diff --git a/item/__pycache__/forms.cpython-38.pyc b/item/__pycache__/forms.cpython-38.pyc
new file mode 100644
index 0000000..457b426
Binary files /dev/null and b/item/__pycache__/forms.cpython-38.pyc differ
diff --git a/item/__pycache__/models.cpython-38.pyc b/item/__pycache__/models.cpython-38.pyc
new file mode 100644
index 0000000..9048f0a
Binary files /dev/null and b/item/__pycache__/models.cpython-38.pyc differ
diff --git a/item/__pycache__/urls.cpython-38.pyc b/item/__pycache__/urls.cpython-38.pyc
new file mode 100644
index 0000000..c5c1715
Binary files /dev/null and b/item/__pycache__/urls.cpython-38.pyc differ
diff --git a/item/__pycache__/views.cpython-38.pyc b/item/__pycache__/views.cpython-38.pyc
new file mode 100644
index 0000000..8522ede
Binary files /dev/null and b/item/__pycache__/views.cpython-38.pyc differ
diff --git a/item/admin.py b/item/admin.py
new file mode 100644
index 0000000..28ff820
--- /dev/null
+++ b/item/admin.py
@@ -0,0 +1,8 @@
+from django.contrib import admin
+
+#TUDO FAZ REFERENCIA A TELA DE ADMIN DO SITE
+
+from .models import Category, Item
+
+admin.site.register(Category)
+admin.site.register(Item)
\ No newline at end of file
diff --git a/item/apps.py b/item/apps.py
new file mode 100644
index 0000000..bed08f9
--- /dev/null
+++ b/item/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+class ItemConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'item'
diff --git a/item/forms.py b/item/forms.py
new file mode 100644
index 0000000..7e2b1f7
--- /dev/null
+++ b/item/forms.py
@@ -0,0 +1,46 @@
+from django import forms
+
+from .models import Item
+
+INPUT_CLASSES = 'w-full py-4 px-6 rounded-xl border'
+
+class NewItemForm(forms.ModelForm):
+ class Meta:
+ model = Item
+ fields = ('category', 'name', 'description', 'price', 'image',)
+ widgets = {
+ 'category': forms.Select(attrs={
+ 'class': INPUT_CLASSES
+ }),
+ 'name': forms.TextInput(attrs={
+ 'class': INPUT_CLASSES
+ }),
+ 'description': forms.Textarea(attrs={
+ 'class': INPUT_CLASSES
+ }),
+ 'price': forms.TextInput(attrs={
+ 'class': INPUT_CLASSES
+ }),
+ 'image': forms.FileInput(attrs={
+ 'class': INPUT_CLASSES
+ })
+ }
+
+class EditItemForm(forms.ModelForm):
+ class Meta:
+ model = Item
+ fields = ('name', 'description', 'price', 'image', 'is_sold')
+ widgets = {
+ 'name': forms.TextInput(attrs={
+ 'class': INPUT_CLASSES
+ }),
+ 'description': forms.Textarea(attrs={
+ 'class': INPUT_CLASSES
+ }),
+ 'price': forms.TextInput(attrs={
+ 'class': INPUT_CLASSES
+ }),
+ 'image': forms.FileInput(attrs={
+ 'class': INPUT_CLASSES
+ })
+ }
\ No newline at end of file
diff --git a/item/migrations/0001_initial.py b/item/migrations/0001_initial.py
new file mode 100644
index 0000000..63d5b89
--- /dev/null
+++ b/item/migrations/0001_initial.py
@@ -0,0 +1,21 @@
+# Generated by Django 4.2.7 on 2023-11-26 04:41
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Category',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255)),
+ ],
+ ),
+ ]
diff --git a/item/migrations/0002_alter_category_options_item.py b/item/migrations/0002_alter_category_options_item.py
new file mode 100644
index 0000000..0fefa83
--- /dev/null
+++ b/item/migrations/0002_alter_category_options_item.py
@@ -0,0 +1,34 @@
+# Generated by Django 4.2.7 on 2023-11-26 04:56
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('item', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='category',
+ options={'ordering': ('name',), 'verbose_name_plural': 'Categories'},
+ ),
+ migrations.CreateModel(
+ name='Item',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255)),
+ ('description', models.TextField(blank=True, null=True)),
+ ('price', models.FloatField()),
+ ('image', models.ImageField(blank=True, null=True, upload_to='items_images')),
+ ('is_sold', models.BooleanField(default=False)),
+ ('create_at', models.DateTimeField(auto_now_add=True)),
+ ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='item.category')),
+ ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/item/migrations/0003_rename_create_at_item_created_at_alter_item_image.py b/item/migrations/0003_rename_create_at_item_created_at_alter_item_image.py
new file mode 100644
index 0000000..92ed121
--- /dev/null
+++ b/item/migrations/0003_rename_create_at_item_created_at_alter_item_image.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.2.7 on 2023-11-27 07:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('item', '0002_alter_category_options_item'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='item',
+ old_name='create_at',
+ new_name='created_at',
+ ),
+ migrations.AlterField(
+ model_name='item',
+ name='image',
+ field=models.ImageField(blank=True, null=True, upload_to='item_images'),
+ ),
+ ]
diff --git a/item/migrations/__init__.py b/item/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/item/migrations/__pycache__/0001_initial.cpython-38.pyc b/item/migrations/__pycache__/0001_initial.cpython-38.pyc
new file mode 100644
index 0000000..729ab98
Binary files /dev/null and b/item/migrations/__pycache__/0001_initial.cpython-38.pyc differ
diff --git a/item/migrations/__pycache__/0002_alter_category_options_item.cpython-38.pyc b/item/migrations/__pycache__/0002_alter_category_options_item.cpython-38.pyc
new file mode 100644
index 0000000..d101ca2
Binary files /dev/null and b/item/migrations/__pycache__/0002_alter_category_options_item.cpython-38.pyc differ
diff --git a/item/migrations/__pycache__/0003_rename_create_at_item_created_at_alter_item_image.cpython-38.pyc b/item/migrations/__pycache__/0003_rename_create_at_item_created_at_alter_item_image.cpython-38.pyc
new file mode 100644
index 0000000..11f501a
Binary files /dev/null and b/item/migrations/__pycache__/0003_rename_create_at_item_created_at_alter_item_image.cpython-38.pyc differ
diff --git a/item/migrations/__pycache__/__init__.cpython-38.pyc b/item/migrations/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..e14e568
Binary files /dev/null and b/item/migrations/__pycache__/__init__.cpython-38.pyc differ
diff --git a/item/models.py b/item/models.py
new file mode 100644
index 0000000..2cb7afc
--- /dev/null
+++ b/item/models.py
@@ -0,0 +1,25 @@
+from django.contrib.auth.models import User
+from django.db import models
+
+class Category(models.Model):
+ name = models.CharField(max_length=255)
+
+ class Meta:
+ ordering = ('name',)
+ verbose_name_plural = 'Categories'
+
+ def __str__(self):
+ return self.name
+
+class Item(models.Model):
+ category = models.ForeignKey(Category, related_name='items', on_delete=models.CASCADE)
+ name = models.CharField(max_length=255)
+ description = models.TextField(blank=True, null=True)
+ price = models.FloatField()
+ image = models.ImageField(upload_to='item_images', blank=True, null=True)
+ is_sold = models.BooleanField(default=False)
+ created_by = models.ForeignKey(User, related_name='items', on_delete=models.CASCADE)
+ created_at = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return self.name
\ No newline at end of file
diff --git a/item/templates/item/detail.html b/item/templates/item/detail.html
new file mode 100644
index 0000000..afef7f0
--- /dev/null
+++ b/item/templates/item/detail.html
@@ -0,0 +1,56 @@
+{% extends 'core/base.html' %}
+
+{% block title %}{{ item.name }}{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+
{{ item.name }}
+
Price: {{ item.price }}
+
Seller: {{ item.created_by.username }}
+
+ {% if item.description %}
+
+ Description:
+ {{ item.description }}
+
+ {% endif %}
+
+ {% if request.user == item.created_by %}
+
+ {% else %}
+
Contact seller
+ {% endif %}
+
+
+
+
+
Related items
+
+
+ {% for item in related_items %}
+
+ {% endfor %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/item/templates/item/form.html b/item/templates/item/form.html
new file mode 100644
index 0000000..f2d988b
--- /dev/null
+++ b/item/templates/item/form.html
@@ -0,0 +1,27 @@
+{% extends 'core/base.html' %}
+
+{% block title %}{{ title }}{% endblock %}
+
+{% block content %}
+{{ title }}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/item/templates/item/items.html b/item/templates/item/items.html
new file mode 100644
index 0000000..87344d3
--- /dev/null
+++ b/item/templates/item/items.html
@@ -0,0 +1,53 @@
+{% extends 'core/base.html' %}
+
+{% block title %}Items{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+
Categories
+
+
+
+
+
+
Clear filters
+
+
+
+
+
+ {% for item in items %}
+
+ {% endfor %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/item/tests.py b/item/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/item/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/item/urls.py b/item/urls.py
new file mode 100644
index 0000000..7f77ef7
--- /dev/null
+++ b/item/urls.py
@@ -0,0 +1,13 @@
+from django.urls import path
+
+from . import views
+
+app_name = 'item'
+
+urlpatterns = [
+ path('', views.items, name='items'),
+ path('new/', views.new, name='new'),
+ path('/', views.detail, name='detail'),
+ path('/delete/', views.delete, name='delete'),
+ path('/edit/', views.edit, name='edit'),
+]
\ No newline at end of file
diff --git a/item/views.py b/item/views.py
new file mode 100644
index 0000000..6eb1ae1
--- /dev/null
+++ b/item/views.py
@@ -0,0 +1,81 @@
+from django.contrib.auth.decorators import login_required
+from django.db.models import Q
+from django.shortcuts import render, get_object_or_404, redirect
+
+from .forms import NewItemForm, EditItemForm
+from .models import Category, Item
+
+def items(request):
+ query = request.GET.get('query', '')
+ category_id = request.GET.get('category', 0)
+ categories = Category.objects.all()
+ items = Item.objects.filter(is_sold=False)
+
+ if category_id:
+ items = items.filter(category_id=category_id)
+
+ if query:
+ items = items.filter(Q(name__icontains=query) | Q(description__icontains=query))
+
+ items = items.order_by('-price')
+
+ return render(request, 'item/items.html', {
+ 'items': items,
+ 'query': query,
+ 'categories': categories,
+ 'category_id': int(category_id)
+ })
+
+def detail(request, pk):
+ item = get_object_or_404(Item, pk=pk)
+ related_items = Item.objects.filter(category=item.category, is_sold=False).exclude(pk=pk)[0:3]
+
+ return render(request, 'item/detail.html', {
+ 'item': item,
+ 'related_items': related_items
+ })
+
+@login_required
+def new(request):
+ if request.method == 'POST':
+ form = NewItemForm(request.POST, request.FILES)
+
+ if form.is_valid():
+ item = form.save(commit=False)
+ item.created_by = request.user
+ item.save()
+
+ return redirect('item:detail', pk=item.id)
+ else:
+ form = NewItemForm()
+
+ return render(request, 'item/form.html', {
+ 'form': form,
+ 'title': 'New item',
+ })
+
+@login_required
+def edit(request, pk):
+ item = get_object_or_404(Item, pk=pk, created_by=request.user)
+
+ if request.method == 'POST':
+ form = EditItemForm(request.POST, request.FILES, instance=item)
+
+ if form.is_valid():
+ form.save()
+
+ return redirect('item:detail', pk=item.id)
+ else:
+ form = EditItemForm(instance=item)
+
+ return render(request, 'item/form.html', {
+ 'form': form,
+ 'title': 'Edit item',
+ })
+
+@login_required
+def delete(request, pk):
+ item = get_object_or_404(Item, pk=pk, created_by=request.user)
+ item.delete()
+
+ return redirect('dashboard:index')
\ No newline at end of file
diff --git a/manage.py b/manage.py
new file mode 100644
index 0000000..44c2620
--- /dev/null
+++ b/manage.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+ """Run administrative tasks."""
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'brainwave.settings')
+ try:
+ from django.core.management import execute_from_command_line
+ except ImportError as exc:
+ raise ImportError(
+ "Couldn't import Django. Are you sure it's installed and "
+ "available on your PYTHONPATH environment variable? Did you "
+ "forget to activate a virtual environment?"
+ ) from exc
+ execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/media/item_images/068fff422032b9bc512f69ea4fcdc4b5.jpg b/media/item_images/068fff422032b9bc512f69ea4fcdc4b5.jpg
new file mode 100644
index 0000000..c05a2dd
Binary files /dev/null and b/media/item_images/068fff422032b9bc512f69ea4fcdc4b5.jpg differ
diff --git a/media/item_images/22e62412b0d7e675d760eb5c436574c5.png b/media/item_images/22e62412b0d7e675d760eb5c436574c5.png
new file mode 100644
index 0000000..def232a
Binary files /dev/null and b/media/item_images/22e62412b0d7e675d760eb5c436574c5.png differ
diff --git a/media/item_images/5c0afb574f45593454b3a16634235716.jpg b/media/item_images/5c0afb574f45593454b3a16634235716.jpg
new file mode 100644
index 0000000..b16d844
Binary files /dev/null and b/media/item_images/5c0afb574f45593454b3a16634235716.jpg differ
diff --git a/media/item_images/5c0afb574f45593454b3a16634235716_guDBwKc.jpg b/media/item_images/5c0afb574f45593454b3a16634235716_guDBwKc.jpg
new file mode 100644
index 0000000..b16d844
Binary files /dev/null and b/media/item_images/5c0afb574f45593454b3a16634235716_guDBwKc.jpg differ
diff --git a/media/items_images/6abfbbb052f77a936a5b0af80c118543.jpg b/media/items_images/6abfbbb052f77a936a5b0af80c118543.jpg
new file mode 100644
index 0000000..5041f86
Binary files /dev/null and b/media/items_images/6abfbbb052f77a936a5b0af80c118543.jpg differ
diff --git a/media/items_images/download.jpg b/media/items_images/download.jpg
new file mode 100644
index 0000000..3d47d5d
Binary files /dev/null and b/media/items_images/download.jpg differ
diff --git a/pgs/create_post.html b/pgs/create_post.html
deleted file mode 100644
index b4a1dff..0000000
--- a/pgs/create_post.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
“Conectando mentes acadêmicas” - GRAN
-
Brainwave
-
Network
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pgs/login.html b/pgs/login.html
deleted file mode 100644
index 3a363d9..0000000
--- a/pgs/login.html
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
“Conectando mentes acadêmicas” - GRAN
-
Brainwave
-
Network
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/post/__init__.py b/post/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/post/__pycache__/__init__.cpython-38.pyc b/post/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..29e0b59
Binary files /dev/null and b/post/__pycache__/__init__.cpython-38.pyc differ
diff --git a/post/__pycache__/admin.cpython-38.pyc b/post/__pycache__/admin.cpython-38.pyc
new file mode 100644
index 0000000..39829e9
Binary files /dev/null and b/post/__pycache__/admin.cpython-38.pyc differ
diff --git a/post/__pycache__/apps.cpython-38.pyc b/post/__pycache__/apps.cpython-38.pyc
new file mode 100644
index 0000000..4974b51
Binary files /dev/null and b/post/__pycache__/apps.cpython-38.pyc differ
diff --git a/post/__pycache__/forms.cpython-38.pyc b/post/__pycache__/forms.cpython-38.pyc
new file mode 100644
index 0000000..97bfa78
Binary files /dev/null and b/post/__pycache__/forms.cpython-38.pyc differ
diff --git a/post/__pycache__/models.cpython-38.pyc b/post/__pycache__/models.cpython-38.pyc
new file mode 100644
index 0000000..3e3b660
Binary files /dev/null and b/post/__pycache__/models.cpython-38.pyc differ
diff --git a/post/__pycache__/urls.cpython-38.pyc b/post/__pycache__/urls.cpython-38.pyc
new file mode 100644
index 0000000..6d1ad95
Binary files /dev/null and b/post/__pycache__/urls.cpython-38.pyc differ
diff --git a/post/__pycache__/views.cpython-38.pyc b/post/__pycache__/views.cpython-38.pyc
new file mode 100644
index 0000000..17cdd6c
Binary files /dev/null and b/post/__pycache__/views.cpython-38.pyc differ
diff --git a/post/admin.py b/post/admin.py
new file mode 100644
index 0000000..a58fa43
--- /dev/null
+++ b/post/admin.py
@@ -0,0 +1,7 @@
+from django.contrib import admin
+
+
+from .models import Category, Post
+
+admin.site.register(Category)
+admin.site.register(Post)
\ No newline at end of file
diff --git a/post/apps.py b/post/apps.py
new file mode 100644
index 0000000..69463e6
--- /dev/null
+++ b/post/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class PostConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'post'
diff --git a/post/forms.py b/post/forms.py
new file mode 100644
index 0000000..9b67790
--- /dev/null
+++ b/post/forms.py
@@ -0,0 +1,44 @@
+from django import forms
+
+from .models import Post, Comment
+
+INPUT_CLASSES = 'w-full py-4 px-6 rounded-xl border'
+
+class NewPostForm(forms.ModelForm):
+ class Meta:
+ model = Post
+ fields = ('titulo', 'texto')
+ widgets = {
+ 'titulo': forms.TextInput(attrs={
+ 'placeholder': 'Título',
+ 'class': INPUT_CLASSES
+ }),
+ 'texto': forms.Textarea(attrs={
+ 'placeholder': 'Escreva sua publicação',
+ 'class': INPUT_CLASSES
+ }),
+ }
+
+class CommentForm(forms.ModelForm):
+ class Meta:
+ model = Comment
+ fields = ['texto']
+ widgets = {
+ 'texto': forms.Textarea(attrs={
+ 'placeholder': 'Escreva seu comentário',
+ 'class': INPUT_CLASSES
+ }),
+ }
+
+class EditPostForm(forms.ModelForm):
+ class Meta:
+ model = Post
+ fields = ('titulo', 'texto')
+ widgets = {
+ 'titulo': forms.TextInput(attrs={
+ 'class': INPUT_CLASSES
+ }),
+ 'texto': forms.Textarea(attrs={
+ 'class': INPUT_CLASSES
+ })
+ }
\ No newline at end of file
diff --git a/post/migrations/0001_initial.py b/post/migrations/0001_initial.py
new file mode 100644
index 0000000..c6f0e14
--- /dev/null
+++ b/post/migrations/0001_initial.py
@@ -0,0 +1,39 @@
+# Generated by Django 4.2.7 on 2023-11-27 19:31
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Category',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255)),
+ ],
+ options={
+ 'verbose_name_plural': 'Categories',
+ 'ordering': ('name',),
+ },
+ ),
+ migrations.CreateModel(
+ name='Post',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255)),
+ ('description', models.TextField(blank=True, null=True)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='posts', to='post.category')),
+ ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='posts', to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/post/migrations/0002_remove_post_category_remove_post_description_and_more.py b/post/migrations/0002_remove_post_category_remove_post_description_and_more.py
new file mode 100644
index 0000000..705a526
--- /dev/null
+++ b/post/migrations/0002_remove_post_category_remove_post_description_and_more.py
@@ -0,0 +1,36 @@
+# Generated by Django 4.2.7 on 2023-11-28 02:09
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('post', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='post',
+ name='category',
+ ),
+ migrations.RemoveField(
+ model_name='post',
+ name='description',
+ ),
+ migrations.RemoveField(
+ model_name='post',
+ name='name',
+ ),
+ migrations.AddField(
+ model_name='post',
+ name='texto',
+ field=models.TextField(default='Seu valor padrão aqui', max_length=255),
+ ),
+ migrations.AddField(
+ model_name='post',
+ name='titulo',
+ field=models.CharField(default='Seu valor padrao', max_length=50),
+ preserve_default=False,
+ ),
+ ]
diff --git a/post/migrations/0003_comment.py b/post/migrations/0003_comment.py
new file mode 100644
index 0000000..fe2acc9
--- /dev/null
+++ b/post/migrations/0003_comment.py
@@ -0,0 +1,26 @@
+# Generated by Django 4.2.7 on 2023-11-28 03:33
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('post', '0002_remove_post_category_remove_post_description_and_more'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Comment',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('texto', models.TextField()),
+ ('data_criacao', models.DateTimeField(auto_now_add=True)),
+ ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='post.post')),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/post/migrations/0004_comment_likes_post_likes_alter_post_texto.py b/post/migrations/0004_comment_likes_post_likes_alter_post_texto.py
new file mode 100644
index 0000000..397350e
--- /dev/null
+++ b/post/migrations/0004_comment_likes_post_likes_alter_post_texto.py
@@ -0,0 +1,30 @@
+# Generated by Django 4.2.7 on 2023-11-28 05:13
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('post', '0003_comment'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='comment',
+ name='likes',
+ field=models.ManyToManyField(blank=True, related_name='comment_likes', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='post',
+ name='likes',
+ field=models.ManyToManyField(blank=True, related_name='post_likes', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AlterField(
+ model_name='post',
+ name='texto',
+ field=models.TextField(default='', max_length=255),
+ ),
+ ]
diff --git a/post/migrations/0005_alter_comment_likes_alter_post_likes.py b/post/migrations/0005_alter_comment_likes_alter_post_likes.py
new file mode 100644
index 0000000..d75fdb8
--- /dev/null
+++ b/post/migrations/0005_alter_comment_likes_alter_post_likes.py
@@ -0,0 +1,25 @@
+# Generated by Django 4.2.7 on 2023-11-28 06:10
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('post', '0004_comment_likes_post_likes_alter_post_texto'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='comment',
+ name='likes',
+ field=models.ManyToManyField(related_name='comment_likes', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AlterField(
+ model_name='post',
+ name='likes',
+ field=models.ManyToManyField(related_name='post_likes', to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/post/migrations/0006_alter_comment_likes_alter_post_likes.py b/post/migrations/0006_alter_comment_likes_alter_post_likes.py
new file mode 100644
index 0000000..ae8a35c
--- /dev/null
+++ b/post/migrations/0006_alter_comment_likes_alter_post_likes.py
@@ -0,0 +1,25 @@
+# Generated by Django 4.2.7 on 2023-11-28 08:30
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('post', '0005_alter_comment_likes_alter_post_likes'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='comment',
+ name='likes',
+ field=models.ManyToManyField(blank=True, related_name='comment_likes', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AlterField(
+ model_name='post',
+ name='likes',
+ field=models.ManyToManyField(blank=True, related_name='post_likes', to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/post/migrations/__init__.py b/post/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/post/migrations/__pycache__/0001_initial.cpython-38.pyc b/post/migrations/__pycache__/0001_initial.cpython-38.pyc
new file mode 100644
index 0000000..69961f0
Binary files /dev/null and b/post/migrations/__pycache__/0001_initial.cpython-38.pyc differ
diff --git a/post/migrations/__pycache__/0002_remove_post_category_remove_post_description_and_more.cpython-38.pyc b/post/migrations/__pycache__/0002_remove_post_category_remove_post_description_and_more.cpython-38.pyc
new file mode 100644
index 0000000..a5c2974
Binary files /dev/null and b/post/migrations/__pycache__/0002_remove_post_category_remove_post_description_and_more.cpython-38.pyc differ
diff --git a/post/migrations/__pycache__/0003_comment.cpython-38.pyc b/post/migrations/__pycache__/0003_comment.cpython-38.pyc
new file mode 100644
index 0000000..a109750
Binary files /dev/null and b/post/migrations/__pycache__/0003_comment.cpython-38.pyc differ
diff --git a/post/migrations/__pycache__/0004_comment_likes_post_likes_alter_post_texto.cpython-38.pyc b/post/migrations/__pycache__/0004_comment_likes_post_likes_alter_post_texto.cpython-38.pyc
new file mode 100644
index 0000000..75d45f7
Binary files /dev/null and b/post/migrations/__pycache__/0004_comment_likes_post_likes_alter_post_texto.cpython-38.pyc differ
diff --git a/post/migrations/__pycache__/0005_alter_comment_likes_alter_post_likes.cpython-38.pyc b/post/migrations/__pycache__/0005_alter_comment_likes_alter_post_likes.cpython-38.pyc
new file mode 100644
index 0000000..2af65ad
Binary files /dev/null and b/post/migrations/__pycache__/0005_alter_comment_likes_alter_post_likes.cpython-38.pyc differ
diff --git a/post/migrations/__pycache__/0006_alter_comment_likes_alter_post_likes.cpython-38.pyc b/post/migrations/__pycache__/0006_alter_comment_likes_alter_post_likes.cpython-38.pyc
new file mode 100644
index 0000000..7908bff
Binary files /dev/null and b/post/migrations/__pycache__/0006_alter_comment_likes_alter_post_likes.cpython-38.pyc differ
diff --git a/post/migrations/__pycache__/__init__.cpython-38.pyc b/post/migrations/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..4517c8f
Binary files /dev/null and b/post/migrations/__pycache__/__init__.cpython-38.pyc differ
diff --git a/post/models.py b/post/models.py
new file mode 100644
index 0000000..e4cbc0d
--- /dev/null
+++ b/post/models.py
@@ -0,0 +1,29 @@
+from django.contrib.auth.models import User
+from django.db import models
+
+class Category(models.Model):
+ name = models.CharField(max_length=255)
+
+ class Meta:
+ ordering = ('name',)
+ verbose_name_plural = 'Categories'
+
+ def __str__(self):
+ return self.name
+
+class Post(models.Model):
+ titulo = models.CharField(max_length=50)
+ texto = models.TextField(max_length=255, default='')
+ created_by = models.ForeignKey(User, related_name='posts', on_delete=models.CASCADE)
+ created_at = models.DateTimeField(auto_now_add=True)
+ likes = models.ManyToManyField(User, related_name='post_likes', blank=True)
+
+ def __str__(self):
+ return self.titulo
+
+class Comment(models.Model):
+ post = models.ForeignKey(Post, on_delete=models.CASCADE)
+ user = models.ForeignKey(User, on_delete=models.CASCADE)
+ texto = models.TextField()
+ data_criacao = models.DateTimeField(auto_now_add=True)
+ likes = models.ManyToManyField(User, related_name='comment_likes', blank=True)
diff --git a/post/templates/create_post.html b/post/templates/create_post.html
new file mode 100644
index 0000000..82388c4
--- /dev/null
+++ b/post/templates/create_post.html
@@ -0,0 +1,84 @@
+{% load static %}
+
+
+
+
+
+ {% static 'css/index.css' %}
+
+
+
+
+ {% block title %}Criar Post | Brainwave{% endblock %}
+
+
+
+
+
+
+
+
+
“Conectando mentes acadêmicas” - GRAN
+
Brainwave
+
Network
+
+
+
+
+
+
+
+
+ {% csrf_token %}
+
+ {{ form.titulo }}
+
+ {{ form.texto }}
+
+ {% if form.errors or form.non_field_errors %}
+
+ {% for field in form %}
+ {{ field.errors }}
+ {% endfor %}
+
+ {{ form.non_field_errors }}
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/post/templates/post.html b/post/templates/post.html
new file mode 100644
index 0000000..01eaeb6
--- /dev/null
+++ b/post/templates/post.html
@@ -0,0 +1,168 @@
+{% load static %}
+
+
+
+
+
+
+
+
+
+
+
+ {% block title %}Post | Brainwave{% endblock %}
+
+
+
+
+
+
+
+
+
“Conectando mentes acadêmicas” - GRAN
+
Brainwave
+
Network
+
+
+
+
+
+
+
+
+
+
+
{{ post.created_by.username }}
+
{{ post.titulo }}
+ {% if post.created_by == request.user %}
+
+ {% csrf_token %}
+
+
+
+
+ {% endif %}
+
+
+
+
+
{{ post.texto }}
+
+
+ {{ post.likes.count }}
+
+
+
+
+
+
+
+
+ {% csrf_token %}
+ {{ comment_form.texto }}
+
+
+
+
+
+ {% for comment in comments %}
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
diff --git a/post/tests.py b/post/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/post/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/post/urls.py b/post/urls.py
new file mode 100644
index 0000000..90867d8
--- /dev/null
+++ b/post/urls.py
@@ -0,0 +1,18 @@
+from django.urls import path
+
+from . import views
+from .views import post_detail
+
+app_name = 'post'
+
+urlpatterns = [
+ path('', views.posts, name='posts'),
+ path('new/', views.new, name='new'),
+ path('
/', views.detail, name='detail'),
+ path('/delete/', views.delete, name='delete'),
+ path('/', post_detail, name='post_detail'),
+ path('/edit/', views.edit, name='edit'),
+ path('/like/', views.like_post, name='like_post'),
+ path('comment//like/', views.like_comment, name='like_comment'),
+ path('comment//delete/', views.delete_comment, name='delete_comment'),
+]
\ No newline at end of file
diff --git a/post/views.py b/post/views.py
new file mode 100644
index 0000000..46bb704
--- /dev/null
+++ b/post/views.py
@@ -0,0 +1,163 @@
+from django.contrib.auth.decorators import login_required
+from django.db.models import Q
+from django.shortcuts import render, get_object_or_404, redirect
+from django.http import JsonResponse
+from django.contrib import messages
+from django.core.exceptions import PermissionDenied
+from .forms import NewPostForm, EditPostForm, CommentForm
+from .models import Category, Post, Comment
+
+
+def posts(request):
+ query = request.GET.get('query', '')
+ category_id = request.GET.get('category', 0)
+ categories = Category.objects.all()
+ posts = Post.objects.all()
+
+ if category_id:
+ posts = posts.filter(category_id=category_id)
+
+ if query:
+ posts = posts.filter(Q(titulo__icontains=query) | Q(texto__icontains=query))
+
+ return render(request, 'post/posts.html', {
+ 'posts': posts,
+ 'query': query,
+ 'categories': categories,
+ 'category_id': int(category_id)
+ })
+
+def post_detail(request, post_id):
+ post = get_object_or_404(Post, id=post_id)
+ comments = Comment.objects.filter(post=post)
+
+ if request.method == 'POST':
+ comment_form = CommentForm(request.POST)
+ if comment_form.is_valid():
+ comment = comment_form.save(commit=False)
+ comment.post = post
+ comment.user = request.user # ou qualquer método que você usa para obter o usuário atual
+ comment.save()
+ else:
+ comment_form = CommentForm()
+
+ return render(request, 'post_detail.html', {'post': post, 'comments': comments, 'comment_form': comment_form})
+
+def detail(request, pk):
+ post = get_object_or_404(Post, pk=pk)
+
+ if request.method == 'POST':
+ comment_form = CommentForm(request.POST)
+ if comment_form.is_valid():
+ comment = comment_form.save(commit=False)
+ comment.post = post
+ comment.user = request.user
+ comment.save()
+ else:
+ comment_form = CommentForm()
+
+ comments = Comment.objects.filter(post=post)
+
+ return render(request, 'post.html', {
+ 'post': post,
+ 'comments': comments,
+ 'comment_form': comment_form,
+ })
+
+
+@login_required
+def new(request):
+ if request.method == 'POST':
+ form = NewPostForm(request.POST, request.FILES)
+
+ if form.is_valid():
+ post = form.save(commit=False)
+ post.created_by = request.user
+ post.save()
+
+ return redirect('post:detail', pk=post.id)
+ else:
+ form = NewPostForm()
+
+ return render(request, 'create_post.html', {
+ 'form': form,
+ 'title': 'New post',
+ })
+
+@login_required
+def edit(request, pk):
+ post = get_object_or_404(Post, pk=pk, created_by=request.user)
+
+ if request.method == 'POST':
+ form = EditPostForm(request.POST, request.FILES, instance=post)
+
+ if form.is_valid():
+ form.save()
+
+ return redirect('post:detail', pk=post.id)
+ else:
+ form = EditPostForm(instance=post)
+
+ return render(request, 'post.html', {
+ 'form': form,
+ 'title': 'Edit post',
+ })
+
+@login_required
+def delete(request, pk):
+ post = get_object_or_404(Post, pk=pk, created_by=request.user)
+
+ if request.method == 'POST':
+ post.delete()
+ return redirect('core:brainwave')
+
+ # Se o usuário não for o criador do post, levante uma exceção de permissão
+ raise PermissionDenied
+
+@login_required
+def like_post(request, post_id):
+ post = get_object_or_404(Post, id=post_id)
+
+ # Verifica se o usuário já curtiu o post
+ liked = post.likes.filter(id=request.user.id).exists()
+
+ if liked:
+ post.likes.remove(request.user)
+ else:
+ post.likes.add(request.user)
+
+ likes_count = post.likes.count()
+
+ return JsonResponse({'liked': not liked, 'likes_count': likes_count})
+
+@login_required
+def like_comment(request, comment_id):
+ comment = get_object_or_404(Comment, id=comment_id)
+
+ # Verifica se o usuário já curtiu o comentário
+ liked = comment.likes.filter(id=request.user.id).exists()
+
+ if liked:
+ comment.likes.remove(request.user)
+ else:
+ comment.likes.add(request.user)
+
+ likes_count = comment.likes.count()
+
+ return JsonResponse({'liked': not liked, 'likes_count': likes_count})
+
+@login_required
+def delete_comment(request, pk):
+ comment = get_object_or_404(Comment, pk=pk)
+
+ # Verifica se o usuário logado é o autor do comentário
+ if request.user == comment.user:
+ comment.delete()
+ messages.success(request, 'Comentário excluído com sucesso.')
+ else:
+ messages.error(request, 'Você não tem permissão para excluir este comentário.')
+
+ # Redireciona de volta à página do post ou para onde você desejar
+ return redirect('post:detail', pk=comment.post.pk)
+
+
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..9d77084
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+Django==4.2.7
+Pillow==10.1.0
\ No newline at end of file
{{ comment.user.username }}
+ {% if comment.user == request.user %} + + {% endif %} +{{ comment.texto }}
+{{ comment.likes.count }}
+ +