generated from JustScreaMy/ProjectTemplate
its DOOMed, coz CORS came here :'(
This commit is contained in:
parent
e6c1430e48
commit
b593f68b66
19 changed files with 215 additions and 29 deletions
13
TODO
13
TODO
|
@ -1,24 +1,11 @@
|
|||
Nastylovat:
|
||||
- header nedrží
|
||||
- footer
|
||||
- lazyload načítat o něco dříve (neli zrušit alespoň mimo galerii)
|
||||
|
||||
Naprogramovat:
|
||||
- tlačítko "načíst další aktuality" v komponentě News (možná přidat i novou stránku /aktuality
|
||||
- přidat kalendář
|
||||
- kotvičky
|
||||
- přidat v galerii zvětsovač na obrázky
|
||||
- přidat backend
|
||||
- přidat databázi
|
||||
- kontakty
|
||||
- clanky
|
||||
- kalendar
|
||||
- přidat api
|
||||
- přidat volání na api
|
||||
|
||||
Naplánovat:
|
||||
- kurzy + cena: vyskakovací okno na rezervaci s jménem lekce? jak to vyřešit s kalendářem? (stránka /rezervace)
|
||||
- změnit (logicky) pořadí komponent na hlavní stránce
|
||||
|
||||
Čeká na Ondru:
|
||||
- Důležité kontakty + obrázky jak se dostat nebo vzdálenosti od městské dopravy? přidat do googlu
|
BIN
services/backend/articles/2025/02/19/terkadavid.jpg
Normal file
BIN
services/backend/articles/2025/02/19/terkadavid.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 110 KiB |
|
@ -46,11 +46,15 @@ DEBUG_TOOLBAR_PANELS = [
|
|||
]
|
||||
|
||||
ALLOWED_HOSTS = [
|
||||
"0.0.0.0", "localhost", "127.0.0.1",
|
||||
"localhost",
|
||||
]
|
||||
|
||||
INTERNAL_IPS = [
|
||||
"0.0.0.0", "localhost", "127.0.0.1",
|
||||
"localhost",
|
||||
]
|
||||
|
||||
CORS_ALLOWED_ORIGINS = [
|
||||
"http://localhost:8000",
|
||||
]
|
||||
|
||||
# Application definition
|
||||
|
@ -62,6 +66,7 @@ INSTALLED_APPS = [
|
|||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'tko.apps.TkoConfig',
|
||||
"debug_toolbar",
|
||||
'rest_framework',
|
||||
]
|
||||
|
|
|
@ -15,10 +15,14 @@ Including another URLconf
|
|||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
from django.urls import path
|
||||
from debug_toolbar.toolbar import debug_toolbar_urls
|
||||
|
||||
from tko.views import ContactView, ArticleListView, EventListView
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('create-contact/', ContactView.as_view(), name='create-contact'),
|
||||
path('load-articles/', ArticleListView.as_view(), name='load-articles'),
|
||||
path('load-events/', EventListView.as_view(), name='load-events'),
|
||||
] + debug_toolbar_urls()
|
||||
|
|
|
@ -1,19 +1,29 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
from . import models
|
||||
|
||||
|
||||
@admin.register(models.Contact)
|
||||
class ContactAdmin(admin.ModelAdmin):
|
||||
fields = "__all__"
|
||||
list_display = ['name', 'email', 'phone_number', 'content']
|
||||
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
@admin.register(models.Article)
|
||||
class ArticleAdmin(admin.ModelAdmin):
|
||||
fields = "__all__"
|
||||
list_display = ['title', 'date', 'author']
|
||||
|
||||
|
||||
@admin.register(models.Event)
|
||||
class EventAdmin(admin.ModelAdmin):
|
||||
fields = "__all__"
|
||||
list_display = ['title', 'start_date', 'end_date', 'color']
|
||||
|
|
46
services/backend/tko/migrations/0001_initial.py
Normal file
46
services/backend/tko/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Generated by Django 5.1.5 on 2025-02-19 16:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
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=100)),
|
||||
('content', models.TextField()),
|
||||
('date', models.DateField()),
|
||||
('author', models.CharField(max_length=100)),
|
||||
('active_to', models.DateField(blank=True, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Contact',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('first_name', models.CharField(max_length=100)),
|
||||
('last_name', models.CharField(max_length=100)),
|
||||
('email', models.EmailField(max_length=254)),
|
||||
('phone_number', models.CharField(max_length=16)),
|
||||
('content', models.TextField()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Event',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=100)),
|
||||
('start_date', models.DateTimeField()),
|
||||
('end_date', models.DateTimeField()),
|
||||
('color', models.CharField(max_length=100)),
|
||||
],
|
||||
),
|
||||
]
|
18
services/backend/tko/migrations/0002_article_image.py
Normal file
18
services/backend/tko/migrations/0002_article_image.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.1.5 on 2025-02-19 16:30
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tko', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='article',
|
||||
name='image',
|
||||
field=models.FileField(null=True, upload_to='articles/%Y/%m/%d'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,22 @@
|
|||
# Generated by Django 5.1.5 on 2025-02-19 18:33
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tko', '0002_article_image'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='contact',
|
||||
old_name='first_name',
|
||||
new_name='name',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contact',
|
||||
name='last_name',
|
||||
),
|
||||
]
|
|
@ -2,25 +2,33 @@ from django.db import models
|
|||
|
||||
# Create your models here.
|
||||
class Contact(models.Model):
|
||||
first_name = models.CharField(max_length=100)
|
||||
last_name = models.CharField(max_length=100)
|
||||
name = models.CharField(max_length=100)
|
||||
email = models.EmailField()
|
||||
phone_number = models.CharField(max_length=16)
|
||||
content = models.TextField()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}, {self.email}, {self.phone_number}"
|
||||
|
||||
|
||||
class Article(models.Model):
|
||||
title = models.CharField(max_length=100)
|
||||
content = models.TextField()
|
||||
# image = models.ImageField(upload_to='articles/%Y/%m/%d')
|
||||
image = models.FileField(upload_to='articles/%Y/%m/%d', null=True)
|
||||
date = models.DateField()
|
||||
author = models.CharField(max_length=100)
|
||||
|
||||
active_to = models.DateField(null=True, blank=True) # do not show some invitation after this date
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
title = models.CharField(max_length=100)
|
||||
start_date = models.DateTimeField()
|
||||
end_date = models.DateTimeField()
|
||||
color = models.CharField(max_length=100)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
|
21
services/backend/tko/serializers.py
Normal file
21
services/backend/tko/serializers.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
from tko.models import Contact, Article, Event
|
||||
|
||||
|
||||
class ContactSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Contact
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class ArticleListSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Article
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class EventListSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Event
|
||||
fields = '__all__'
|
|
@ -1,3 +1,22 @@
|
|||
from django.shortcuts import render
|
||||
from rest_framework.generics import ListAPIView, CreateAPIView
|
||||
from rest_framework import permissions
|
||||
|
||||
# Create your views here.
|
||||
from tko.models import Article, Event
|
||||
from tko.serializers import ArticleListSerializer, EventListSerializer, ContactSerializer
|
||||
|
||||
|
||||
class ContactView(CreateAPIView):
|
||||
serializer_class = ContactSerializer
|
||||
permission_classes = [permissions.AllowAny]
|
||||
|
||||
|
||||
class ArticleListView(ListAPIView):
|
||||
queryset = Article.objects.all()
|
||||
serializer_class = ArticleListSerializer
|
||||
permission_classes = [permissions.AllowAny]
|
||||
|
||||
|
||||
class EventListView(ListAPIView):
|
||||
queryset = Event.objects.all()
|
||||
serializer_class = EventListSerializer
|
||||
permission_classes = [permissions.AllowAny]
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import './assets/css/main.css'
|
||||
import {useAPI} from "~/composables/useAPI";
|
||||
|
||||
|
||||
const { error, data } = await useAPI('load-events/', {method: "GET"});
|
||||
|
||||
const value = [new Date()];
|
||||
const events = [
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<v-card class="contact">
|
||||
<v-form v-model="valid" @submit="sendContact">
|
||||
<v-form v-model="valid">
|
||||
<v-container>
|
||||
<v-card-title class="contact__title">Kontaktujte nás!</v-card-title>
|
||||
<v-row>
|
||||
|
@ -51,6 +51,7 @@
|
|||
<v-btn
|
||||
class="contact__button"
|
||||
type="submit"
|
||||
@click.prevent="sendContact"
|
||||
>
|
||||
Poslat
|
||||
</v-btn>
|
||||
|
@ -62,6 +63,7 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import './assets/css/main.css'
|
||||
import {useAPI} from "~/composables/useAPI";
|
||||
|
||||
const valid = ref<boolean>(false);
|
||||
|
||||
|
@ -71,7 +73,15 @@ const phone = ref<string>("");
|
|||
const textField = ref<string>("");
|
||||
|
||||
function sendContact() {
|
||||
console.log("KONTAKT NEZASLAN");
|
||||
useAPI('create-contact/', {
|
||||
method: "POST",
|
||||
body: {
|
||||
name: fullName.value,
|
||||
email: email.value,
|
||||
phone_number: phone.value,
|
||||
content: textField.value,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
|
@ -44,6 +44,11 @@
|
|||
<script setup lang="ts">
|
||||
import './assets/css/main.css'
|
||||
|
||||
import {useAPI} from "~/composables/useAPI";
|
||||
|
||||
const { error, data } = await useAPI('load-articles/', {method: "GET"});
|
||||
console.log(error.value);
|
||||
|
||||
const articles = [
|
||||
{
|
||||
autor: "Bebloid Obecný",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<template>
|
||||
<ClientOnly>
|
||||
<v-layout>
|
||||
<v-app-bar style="position: fixed">
|
||||
<v-app-bar-nav-icon
|
||||
|
@ -49,8 +50,8 @@
|
|||
</v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
|
||||
</v-layout>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
19
services/frontend/composables/useAPI.ts
Normal file
19
services/frontend/composables/useAPI.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import type { UseFetchOptions } from "nuxt/app";
|
||||
|
||||
export function useAPI<T>(
|
||||
endpoint: string,
|
||||
options?: UseFetchOptions<T>,
|
||||
) {
|
||||
if (!endpoint.startsWith("/")) {
|
||||
endpoint = `/${endpoint}`
|
||||
}
|
||||
|
||||
const cfg = useRuntimeConfig()
|
||||
|
||||
const fullUrl = `${cfg.public.backendUrl}${endpoint}`
|
||||
|
||||
return useFetch(
|
||||
fullUrl,
|
||||
{...options}
|
||||
)
|
||||
}
|
|
@ -3,11 +3,17 @@ import vuetify, { transformAssetUrls } from 'vite-plugin-vuetify'
|
|||
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2024-11-01',
|
||||
ssr: false,
|
||||
devtools: { enabled: true },
|
||||
typescript: { typeCheck: true},
|
||||
build: {
|
||||
transpile: ['vuetify'],
|
||||
},
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
backendUrl: process.env.BACKEND_URL ?? "http://localhost:8000"
|
||||
},
|
||||
},
|
||||
modules: [
|
||||
(_options, nuxt) => {
|
||||
nuxt.hooks.hook('vite:extendConfig', (config) => {
|
||||
|
|
|
@ -19,5 +19,7 @@
|
|||
<courses/>
|
||||
<contact-us/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
|
@ -66,6 +66,5 @@ export default defineNuxtPlugin((app) => {
|
|||
}
|
||||
})
|
||||
|
||||
|
||||
app.vueApp.use(vuetify)
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue