├── backend ├── src │ ├── __init__.py │ ├── events │ │ ├── tasks.py │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── tests.py │ │ ├── views.py │ │ ├── apps.py │ │ └── models.py │ ├── orders │ │ ├── tasks.py │ │ ├── __init__.py │ │ ├── validations │ │ │ ├── __init__.py │ │ │ └── shipping_validation.py │ │ ├── admin.py │ │ ├── tests.py │ │ ├── views.py │ │ ├── apps.py │ │ ├── models │ │ │ ├── __init__.py │ │ │ ├── shipping_model.py │ │ │ ├── item_model.py │ │ │ └── order_model.py │ │ └── enums.py │ ├── reviews │ │ ├── tasks.py │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── tests.py │ │ ├── views.py │ │ ├── apps.py │ │ └── models.py │ ├── categories │ │ ├── tasks.py │ │ ├── __init__.py │ │ ├── tests.py │ │ ├── admin.py │ │ ├── views.py │ │ ├── apps.py │ │ └── models.py │ ├── common │ │ ├── __init__.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── tests.py │ │ ├── admin.py │ │ ├── errors │ │ │ ├── constants.py │ │ │ ├── __init__.py │ │ │ └── exceptions.py │ │ ├── types.py │ │ ├── controllers │ │ │ ├── __init__.py │ │ │ └── common_controller.py │ │ ├── apps.py │ │ ├── renderers.py │ │ ├── schemas │ │ │ ├── __init__.py │ │ │ └── basic_schema.py │ │ ├── models.py │ │ ├── permissions.py │ │ ├── responses.py │ │ ├── tasks.py │ │ ├── utils.py │ │ └── mixins.py │ ├── core │ │ ├── settings │ │ │ ├── prod.py │ │ │ ├── __init__.py │ │ │ └── base.py │ │ ├── __init__.py │ │ ├── interceptors │ │ │ ├── __init__.py │ │ │ └── auth_interceptors.py │ │ ├── asgi.py │ │ ├── wsgi.py │ │ ├── celery.py │ │ ├── adds.py │ │ └── config.py │ ├── products │ │ ├── __init__.py │ │ ├── tasks.py │ │ ├── tests.py │ │ ├── admin.py │ │ ├── views.py │ │ ├── apps.py │ │ └── models.py │ ├── users │ │ ├── __init__.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ │ ├── __init__.py │ │ │ │ ├── _private.py │ │ │ │ └── make_superuser.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── old_controllers │ │ │ ├── __init__.py │ │ │ ├── profile_controller.py │ │ │ └── user_controller.py │ │ ├── tests.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── models │ │ │ ├── __init__.py │ │ │ ├── profile_model.py │ │ │ └── user_model.py │ │ ├── services │ │ │ └── __init__.py │ │ ├── interfaces │ │ │ ├── __init__.py │ │ │ ├── user_interface.py │ │ │ └── profile_interface.py │ │ ├── repositories │ │ │ └── __init__.py │ │ ├── types.py │ │ ├── files.py │ │ ├── utils.py │ │ ├── errors │ │ │ ├── profile_error.py │ │ │ ├── __init__.py │ │ │ └── user_error.py │ │ ├── validations │ │ │ ├── __init__.py │ │ │ ├── user_validation.py │ │ │ └── profile_validation.py │ │ ├── enums.py │ │ ├── schemas │ │ │ ├── schema.py │ │ │ ├── __init__.py │ │ │ └── profile_schema.py │ │ ├── tasks.py │ │ └── controllers.py │ ├── auth │ │ ├── controllers │ │ │ ├── __init__.py │ │ │ └── auth_controller.py │ │ ├── services │ │ │ └── __init__.py │ │ ├── schemas │ │ │ └── __init__.py │ │ ├── tasks.py │ │ ├── errors.py │ │ ├── throttles.py │ │ └── utils.py │ ├── data │ │ ├── managers │ │ │ ├── __init__.py │ │ │ ├── task_manager.py │ │ │ └── mail_manager.py │ │ ├── interfaces │ │ │ ├── client │ │ │ │ └── abstract_client.py │ │ │ ├── handler │ │ │ │ ├── abstract_mail.py │ │ │ │ ├── abstract_phone.py │ │ │ │ ├── abstract_event.py │ │ │ │ ├── abstract_cache.py │ │ │ │ └── abstract_file.py │ │ │ ├── storage │ │ │ │ ├── abstract_cache.py │ │ │ │ └── abstract_cloud.py │ │ │ ├── __init__.py │ │ │ └── managers │ │ │ │ └── abstract_event_manager.py │ │ ├── storages │ │ │ ├── __init__.py │ │ │ └── redis_storage.py │ │ ├── clients │ │ │ ├── __init__.py │ │ │ ├── vonage_client.py │ │ │ ├── redis_client.py │ │ │ ├── mail_client.py │ │ │ ├── minio_client.py │ │ │ ├── amazon_client.py │ │ │ └── celery_client.py │ │ ├── handlers │ │ │ ├── __init__.py │ │ │ ├── template_handler.py │ │ │ ├── mail_handler.py │ │ │ ├── redis_handler.py │ │ │ └── event_handler.py │ │ └── utils.py │ ├── files │ │ ├── schemas.py │ │ ├── errors.py │ │ ├── controllers.py │ │ └── services.py │ └── api.py ├── media │ ├── register.png │ └── files │ │ └── country_codes.csv ├── .gitignore ├── docker │ ├── celery │ │ ├── worker.sh │ │ ├── beat.sh │ │ └── flower.sh │ ├── redis │ │ ├── Dockerfile │ │ └── init.sh │ ├── django.sh │ ├── scripts │ │ └── wait_for_port.sh │ ├── entrypoint.sh │ └── ninja │ │ └── Dockerfile ├── main.py ├── templates │ └── register-mail.html ├── README.md ├── manage.py └── pyproject.toml ├── frontend ├── src │ ├── App.css │ ├── pages │ │ ├── auth │ │ │ ├── LoginPage │ │ │ │ ├── index.tsx │ │ │ │ └── LoginPage.tsx │ │ │ └── RegisterPage │ │ │ │ ├── index.tsx │ │ │ │ └── RegisterPage.tsx │ │ └── HomePage │ │ │ └── HomePage.tsx │ ├── contexts │ │ ├── ThemeContextInterface.tsx │ │ └── ThemeContext.tsx │ ├── components │ │ └── nav │ │ │ ├── index.tsx │ │ │ ├── Header.css │ │ │ ├── ButtonLightDark.tsx │ │ │ └── Header.tsx │ ├── App.tsx │ ├── dev │ │ ├── index.ts │ │ ├── palette.tsx │ │ ├── useInitial.ts │ │ ├── previews.tsx │ │ └── README.md │ ├── vite-env.d.ts │ ├── hooks │ │ └── useTheme.tsx │ ├── index.css │ ├── main.tsx │ ├── routes.tsx │ ├── providers │ │ └── ThemeProvider.tsx │ └── assets │ │ └── react.svg ├── .eslintignore ├── .prettierignore ├── .prettierrc.json ├── docker │ └── Dockerfile ├── tsconfig.node.json ├── index.html ├── .gitignore ├── vite.config.ts ├── tsconfig.json ├── .eslintrc.json ├── package.json ├── README.md └── public │ └── vite.svg ├── .python-version ├── .envs ├── dev │ ├── flower.env │ ├── mail.env │ ├── postgres.env │ ├── redis.env │ ├── minio.env │ ├── react.env │ └── django.env └── .template.env ├── commands └── dev │ ├── run.sh │ ├── run_less_backend.sh │ ├── load-env.sh │ ├── install.sh │ ├── debug.sh │ └── backend │ ├── delete_volume.sh │ ├── delete_migrations_files.sh │ └── makemigrations.sh ├── .dockerignore ├── README.dev.md ├── .pre-commit-config.yaml ├── README.md ├── LICENSE └── .gitignore /backend/src/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.11.7 2 | -------------------------------------------------------------------------------- /backend/src/events/tasks.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/orders/tasks.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/reviews/tasks.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/categories/tasks.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/core/settings/prod.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/events/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/orders/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/products/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/products/tasks.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/reviews/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/users/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/categories/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/core/settings/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/common/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/orders/validations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/users/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/users/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/users/old_controllers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/users/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/users/management/commands/_private.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | src/dev 3 | -------------------------------------------------------------------------------- /backend/src/common/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /backend/src/users/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /backend/src/users/admin.py: -------------------------------------------------------------------------------- 1 | # RegisterPage your models here. 2 | -------------------------------------------------------------------------------- /backend/src/common/admin.py: -------------------------------------------------------------------------------- 1 | # RegisterPage your models here. 2 | -------------------------------------------------------------------------------- /frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package.lock.json 3 | build 4 | -------------------------------------------------------------------------------- /.envs/dev/flower.env: -------------------------------------------------------------------------------- 1 | # flower 2 | CELERY_FLOWER_USER=admin 3 | CELERY_FLOWER_PASSWORD=admin 4 | -------------------------------------------------------------------------------- /backend/src/categories/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /backend/src/events/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /backend/src/events/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /backend/src/events/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /backend/src/orders/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /backend/src/orders/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /backend/src/orders/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /backend/src/products/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /backend/src/reviews/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /backend/src/reviews/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /backend/src/reviews/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /frontend/src/pages/auth/LoginPage/index.tsx: -------------------------------------------------------------------------------- 1 | export { default as LoginPage } from "./LoginPage"; 2 | -------------------------------------------------------------------------------- /backend/src/categories/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /backend/src/categories/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /backend/src/products/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /backend/src/products/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /frontend/src/pages/auth/RegisterPage/index.tsx: -------------------------------------------------------------------------------- 1 | export { default as RegisterPage } from "./RegisterPage"; 2 | -------------------------------------------------------------------------------- /backend/media/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radthenone/olivin_store/HEAD/backend/media/register.png -------------------------------------------------------------------------------- /backend/src/core/__init__.py: -------------------------------------------------------------------------------- 1 | from src.core.celery import celery as celery_app 2 | 3 | __all__ = ("celery_app",) 4 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | ../.python-version 2 | poetry.lock 3 | staticfiles 4 | logs 5 | src/**/migrations/* 6 | VERSION.txt 7 | -------------------------------------------------------------------------------- /backend/src/common/errors/constants.py: -------------------------------------------------------------------------------- 1 | class StatusCodes: 2 | SERVER_ERROR = 500 3 | NOT_FOUND = 404 4 | CONFLICT = 409 5 | -------------------------------------------------------------------------------- /.envs/dev/mail.env: -------------------------------------------------------------------------------- 1 | # email 2 | EMAIL_HOST=127.0.0.1 3 | EMAIL_HOST_USER= 4 | EMAIL_HOST_PASSWORD= 5 | EMAIL_PORT=1025 6 | EMAIL_USE_TLS=False 7 | -------------------------------------------------------------------------------- /backend/src/auth/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from src.auth.controllers.auth_controller import AuthController 2 | 3 | __all__ = ["AuthController"] 4 | -------------------------------------------------------------------------------- /backend/src/auth/services/__init__.py: -------------------------------------------------------------------------------- 1 | from src.auth.services.auth_service import AuthService 2 | 3 | __all__ = [ 4 | "AuthService", 5 | ] 6 | -------------------------------------------------------------------------------- /frontend/src/contexts/ThemeContextInterface.tsx: -------------------------------------------------------------------------------- 1 | export interface ThemeContextProps { 2 | theme: string; 3 | toggleTheme: () => void; 4 | } 5 | -------------------------------------------------------------------------------- /.envs/dev/postgres.env: -------------------------------------------------------------------------------- 1 | POSTGRES_HOST=db 2 | POSTGRES_PORT=5432 3 | POSTGRES_DB=postgres-olivin 4 | POSTGRES_USER=olivin 5 | POSTGRES_PASSWORD=olivin 6 | -------------------------------------------------------------------------------- /frontend/src/components/nav/index.tsx: -------------------------------------------------------------------------------- 1 | export { default as Header } from "./Header"; 2 | export { default as ButtonLightDark } from "./ButtonLightDark"; 3 | -------------------------------------------------------------------------------- /backend/src/common/types.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar 2 | 3 | from pydantic import BaseModel 4 | 5 | SchemaType = TypeVar("SchemaType", bound=BaseModel) 6 | -------------------------------------------------------------------------------- /frontend/src/components/nav/Header.css: -------------------------------------------------------------------------------- 1 | .header { 2 | background-color: red; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | } 7 | -------------------------------------------------------------------------------- /.envs/dev/redis.env: -------------------------------------------------------------------------------- 1 | REDIS_HOST=redis 2 | REDIS_PORT=6379 3 | REDIS_DB=0 4 | REDIS_PASSWORD=some_redis_password 5 | REDIS_URL=redis://:some_redis_password@redis:6379/0 6 | -------------------------------------------------------------------------------- /backend/docker/celery/worker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | sleep 5 7 | 8 | celery -A src.core.celery worker -l INFO -Q tasks,events 9 | -------------------------------------------------------------------------------- /backend/src/common/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from src.common.controllers.common_controller import CommonController 2 | 3 | __all__ = [ 4 | "CommonController", 5 | ] 6 | -------------------------------------------------------------------------------- /.envs/.template.env: -------------------------------------------------------------------------------- 1 | AWS_ACCESS_KEY= 2 | AWS_SECRET_KEY= 3 | AWS_REGION_NAME= 4 | API_BACKEND_URL= 5 | API_FRONTEND_URL= 6 | API_VERSION= 7 | VONAGE_API_KEY= 8 | VONAGE_API_SECRET= 9 | -------------------------------------------------------------------------------- /.envs/dev/minio.env: -------------------------------------------------------------------------------- 1 | MINIO_ROOT_USER=minioadmin 2 | MINIO_ROOT_PASSWORD=minioadmin 3 | MINIO_HOST=minio 4 | MINIO_PORT=9000 5 | BUCKET_NAME=olivin-d2e3e393-9767-413b-b6d5-cf8fd6166de0 6 | -------------------------------------------------------------------------------- /backend/src/common/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CommonConfig(AppConfig): 5 | default_auto_field = "django.db.models.BigAutoField" 6 | name = "src.common" 7 | -------------------------------------------------------------------------------- /backend/src/events/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class EventsConfig(AppConfig): 5 | default_auto_field = "django.db.models.BigAutoField" 6 | name = "src.events" 7 | -------------------------------------------------------------------------------- /backend/src/orders/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class OrdersConfig(AppConfig): 5 | default_auto_field = "django.db.models.BigAutoField" 6 | name = "src.orders" 7 | -------------------------------------------------------------------------------- /backend/src/users/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UsersConfig(AppConfig): 5 | default_auto_field = "django.db.models.BigAutoField" 6 | name = "src.users" 7 | -------------------------------------------------------------------------------- /.envs/dev/react.env: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | WDS_SOCKET_HOST=127.0.0.1 3 | CHOKIDAR_USEPOLLING=true 4 | WATCHPACK_POLLING=true 5 | HOST=0.0.0.0 6 | PORT=3000 7 | API_BACKEND_URL=http://127.0.0.1:8000 8 | -------------------------------------------------------------------------------- /backend/src/reviews/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ReviewsConfig(AppConfig): 5 | default_auto_field = "django.db.models.BigAutoField" 6 | name = "src.reviews" 7 | -------------------------------------------------------------------------------- /backend/src/users/models/__init__.py: -------------------------------------------------------------------------------- 1 | from src.users.models.profile_model import Profile 2 | from src.users.models.user_model import User 3 | 4 | __all__ = [ 5 | "User", 6 | "Profile", 7 | ] 8 | -------------------------------------------------------------------------------- /backend/src/products/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ProductsConfig(AppConfig): 5 | default_auto_field = "django.db.models.BigAutoField" 6 | name = "src.products" 7 | -------------------------------------------------------------------------------- /backend/src/categories/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CategoriesConfig(AppConfig): 5 | default_auto_field = "django.db.models.BigAutoField" 6 | name = "src.categories" 7 | -------------------------------------------------------------------------------- /frontend/src/pages/auth/LoginPage/LoginPage.tsx: -------------------------------------------------------------------------------- 1 | const LoginPage = () => { 2 | return ( 3 |
4 |

Login Page

5 |
6 | ); 7 | }; 8 | 9 | export default LoginPage; 10 | -------------------------------------------------------------------------------- /backend/docker/celery/beat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | 7 | rm -f './celerybeat.pid' 8 | 9 | sleep 5 10 | 11 | celery -A src.core.celery worker -l INFO -Q beats -E -B 12 | -------------------------------------------------------------------------------- /frontend/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "semi": true, 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "useTabs": false, 7 | "trailingComma": "all", 8 | "endOfLine": "auto" 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/core/interceptors/__init__.py: -------------------------------------------------------------------------------- 1 | from src.core.interceptors.auth_interceptors import ( 2 | AuthBearer, 3 | get_user_id, 4 | ) 5 | 6 | __all__ = [ 7 | "AuthBearer", 8 | "get_user_id", 9 | ] 10 | -------------------------------------------------------------------------------- /frontend/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { RouterProvider } from "react-router-dom"; 2 | import router from "./routes.tsx"; 3 | 4 | const App = () => { 5 | return ; 6 | }; 7 | 8 | export default App; 9 | -------------------------------------------------------------------------------- /frontend/src/pages/auth/RegisterPage/RegisterPage.tsx: -------------------------------------------------------------------------------- 1 | const RegisterPage = () => { 2 | return ( 3 |
4 |

Register Page

5 |
6 | ); 7 | }; 8 | 9 | export default RegisterPage; 10 | -------------------------------------------------------------------------------- /backend/src/data/managers/__init__.py: -------------------------------------------------------------------------------- 1 | from src.data.managers.event_manager import EventManager 2 | from src.data.managers.mail_manager import MailManager 3 | 4 | __all__ = [ 5 | "EventManager", 6 | "MailManager", 7 | ] 8 | -------------------------------------------------------------------------------- /frontend/src/dev/index.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useInitial } from "./useInitial"; 3 | 4 | const ComponentPreviews = React.lazy(() => import("./previews")); 5 | 6 | export { ComponentPreviews, useInitial }; 7 | -------------------------------------------------------------------------------- /backend/src/users/services/__init__.py: -------------------------------------------------------------------------------- 1 | from src.users.services.profile_service import ProfileService 2 | from src.users.services.user_service import UserService 3 | 4 | __all__ = [ 5 | "UserService", 6 | "ProfileService", 7 | ] 8 | -------------------------------------------------------------------------------- /frontend/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY package*.json ./ 6 | 7 | RUN npm ci 8 | RUN npm cache clean --force 9 | 10 | COPY . . 11 | 12 | EXPOSE 3000 13 | 14 | CMD ["npm", "run", "dev"] 15 | -------------------------------------------------------------------------------- /backend/docker/redis/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM redis:7.2 2 | 3 | COPY ./docker/redis/init.sh /redis/init.sh 4 | RUN sed -i 's/\r$//g' /redis/init.sh && chmod +x /redis/init.sh 5 | 6 | WORKDIR /redis 7 | 8 | EXPOSE 6379 9 | 10 | CMD ["./init.sh"] 11 | -------------------------------------------------------------------------------- /frontend/src/pages/HomePage/HomePage.tsx: -------------------------------------------------------------------------------- 1 | const HomePage = () => { 2 | return ( 3 |
4 |

Home Page

5 |

{process.env.API_BACKEND_URL}

6 |
7 | ); 8 | }; 9 | 10 | export default HomePage; 11 | -------------------------------------------------------------------------------- /frontend/src/contexts/ThemeContext.tsx: -------------------------------------------------------------------------------- 1 | import { createContext } from "react"; 2 | import { ThemeContextProps } from "./ThemeContextInterface.tsx"; 3 | 4 | export const ThemeContext = createContext( 5 | undefined, 6 | ); 7 | -------------------------------------------------------------------------------- /backend/main.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | import uvicorn 3 | 4 | uvicorn.run( 5 | "src.core.asgi:application", 6 | host="localhost", 7 | port=8080, 8 | log_level="info", 9 | reload=True, 10 | ) 11 | -------------------------------------------------------------------------------- /backend/src/users/interfaces/__init__.py: -------------------------------------------------------------------------------- 1 | from src.users.interfaces.profile_interface import IProfileRepository 2 | from src.users.interfaces.user_interface import IUserRepository 3 | 4 | __all__ = [ 5 | "IUserRepository", 6 | "IProfileRepository", 7 | ] 8 | -------------------------------------------------------------------------------- /commands/dev/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | set -o pipefail 4 | set -o nounset 5 | 6 | source ./commands/dev/load-env.sh 7 | 8 | if [ "${DEBUG}" = 1 ]; then 9 | echo "Starting development" 10 | docker-compose --profile dev start 11 | fi 12 | -------------------------------------------------------------------------------- /backend/src/users/repositories/__init__.py: -------------------------------------------------------------------------------- 1 | from src.users.repositories.profile_repository import ProfileRepository 2 | from src.users.repositories.user_repository import UserRepository 3 | 4 | __all__ = [ 5 | "UserRepository", 6 | "ProfileRepository", 7 | ] 8 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | frontend/node_modules 3 | .envs 4 | commands 5 | .git 6 | .gitignore 7 | .pre-commit-config.yaml 8 | .python-version 9 | LICENSE 10 | *.md 11 | **/site-packages/* 12 | 13 | 14 | 15 | # Allow files and directories 16 | !/src 17 | -------------------------------------------------------------------------------- /backend/src/common/errors/__init__.py: -------------------------------------------------------------------------------- 1 | from src.common.errors.constants import StatusCodes 2 | from src.common.errors.exceptions import BasicHTTPException, HTTPException 3 | 4 | __all__ = [ 5 | "StatusCodes", 6 | "BasicHTTPException", 7 | "HTTPException", 8 | ] 9 | -------------------------------------------------------------------------------- /frontend/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | interface ImportMetaEnv { 3 | readonly API_BACKEND_URL: string; 4 | readonly HOST: string; 5 | readonly PORT: string; 6 | } 7 | 8 | interface ImportMeta { 9 | readonly env: ImportMetaEnv; 10 | } 11 | -------------------------------------------------------------------------------- /backend/src/common/renderers.py: -------------------------------------------------------------------------------- 1 | import orjson 2 | from ninja.renderers import BaseRenderer 3 | 4 | 5 | class ORJSONRenderer(BaseRenderer): 6 | media_type = "application/json" 7 | 8 | def render(self, request, data, *, response_status): 9 | return orjson.dumps(data) 10 | -------------------------------------------------------------------------------- /backend/src/orders/models/__init__.py: -------------------------------------------------------------------------------- 1 | from src.orders.models.item_model import OrderItem 2 | from src.orders.models.order_model import Order 3 | from src.orders.models.shipping_model import Shipping 4 | 5 | __all__ = [ 6 | "Order", 7 | "OrderItem", 8 | "Shipping", 9 | ] 10 | -------------------------------------------------------------------------------- /commands/dev/run_less_backend.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | set -o pipefail 4 | set -o nounset 5 | 6 | source ./commands/dev/load-env.sh 7 | 8 | if [ "${DEBUG}" = 1 ]; then 9 | echo "Starting development wait for backend" 10 | docker-compose --profile less-dev start 11 | fi 12 | -------------------------------------------------------------------------------- /backend/src/users/types.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar 2 | 3 | from django.contrib.auth import get_user_model 4 | 5 | from src.users.models import Profile 6 | 7 | User = get_user_model() 8 | 9 | UserType = TypeVar("UserType", bound=User) 10 | ProfileType = TypeVar("ProfileType", bound=Profile) 11 | -------------------------------------------------------------------------------- /commands/dev/load-env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | set -o pipefail 4 | set -o nounset 5 | 6 | echo "Loading development environment" 7 | source "${PWD}"/.envs/dev/react.env 8 | source "${PWD}"/.envs/dev/django.env 9 | source "${PWD}"/.envs/dev/postgres.env 10 | source "${PWD}"/.envs/dev/redis.env 11 | -------------------------------------------------------------------------------- /backend/src/data/interfaces/client/abstract_client.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class IClient(ABC): 5 | @abstractmethod 6 | def connect(self, *args, **kwargs) -> None: 7 | pass 8 | 9 | @abstractmethod 10 | def disconnect(self, *args, **kwargs) -> None: 11 | pass 12 | -------------------------------------------------------------------------------- /backend/src/data/storages/__init__.py: -------------------------------------------------------------------------------- 1 | from src.data.storages.amazon_storage import AmazonS3Storage 2 | from src.data.storages.minio_storage import MinioStorage 3 | from src.data.storages.redis_storage import RedisStorage 4 | 5 | __all__ = [ 6 | "RedisStorage", 7 | "AmazonS3Storage", 8 | "MinioStorage", 9 | ] 10 | -------------------------------------------------------------------------------- /backend/src/common/schemas/__init__.py: -------------------------------------------------------------------------------- 1 | from src.common.schemas.basic_schema import ( 2 | CreatedAtSchema, 3 | MessageSchema, 4 | PasswordsMatchSchema, 5 | UpdatedAtSchema, 6 | ) 7 | 8 | __all__ = [ 9 | "CreatedAtSchema", 10 | "UpdatedAtSchema", 11 | "MessageSchema", 12 | "PasswordsMatchSchema", 13 | ] 14 | -------------------------------------------------------------------------------- /commands/dev/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | set -o pipefail 4 | set -o nounset 5 | 6 | source ./commands/dev/load-env.sh 7 | 8 | if [ "${DEBUG}" = 1 ]; then 9 | echo "Starting install development" 10 | docker-compose --profile dev up --build -d 11 | docker-compose --profile dev stop 12 | echo "Development created" 13 | fi 14 | -------------------------------------------------------------------------------- /commands/dev/debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | set -o pipefail 4 | set -o nounset 5 | 6 | source ./commands/dev/load-env.sh 7 | 8 | if [ "${DEBUG}" = 1 ]; then 9 | echo "Starting debugging" 10 | docker-compose --profile dev stop 11 | docker-compose --profile dev-less start 12 | docker-compose run --rm --service-ports backend 13 | fi 14 | -------------------------------------------------------------------------------- /frontend/src/hooks/useTheme.tsx: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import { ThemeContext } from "context/ThemeContext.tsx"; 3 | 4 | export const useTheme = () => { 5 | const context = useContext(ThemeContext); 6 | if (!context) { 7 | throw new Error("useTheme must be used within a ThemeProvider"); 8 | } 9 | return context; 10 | }; 11 | -------------------------------------------------------------------------------- /frontend/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true 9 | }, 10 | "include": ["vite.config.ts"], 11 | "exclude": ["node_modules", "build", "dist"] 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/data/interfaces/handler/abstract_mail.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import Any, Optional 3 | 4 | 5 | class IRegistrationEmailHandler(ABC): 6 | @abstractmethod 7 | def send_registration_email( 8 | self, 9 | to_email: str, 10 | context: Optional[dict[str, Any]] = None, 11 | ) -> bool: 12 | pass 13 | -------------------------------------------------------------------------------- /backend/src/users/files.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | 4 | def read_country_codes(file_path) -> dict[str, str]: 5 | country_codes = {} 6 | with open(file_path, mode="r", encoding="utf-8") as file: 7 | reader = csv.reader(file) 8 | next(reader) 9 | for row in reader: 10 | country_codes[row[0].upper()] = row[2] 11 | return country_codes 12 | -------------------------------------------------------------------------------- /backend/src/common/models.py: -------------------------------------------------------------------------------- 1 | import json 2 | import uuid 3 | from typing import Any, Optional 4 | 5 | from django.db import models 6 | from django.utils import timezone 7 | 8 | 9 | class CreatedUpdatedDateModel(models.Model): 10 | created_at = models.DateTimeField(db_index=True, default=timezone.now) 11 | updated_at = models.DateTimeField(auto_now=True) 12 | 13 | class Meta: 14 | abstract = True 15 | -------------------------------------------------------------------------------- /commands/dev/backend/delete_volume.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | set -o pipefail 4 | set -o nounset 5 | 6 | if [ $# -ne 2 ]; then 7 | echo "Need to specify the container and volume names." 8 | echo "delete_volume.sh " 9 | exit 1 10 | fi 11 | 12 | container_name=$1 13 | volume_name=$2 14 | 15 | docker container rm -f "$container_name" 16 | docker volume rm "$volume_name" 17 | -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /backend/src/users/utils.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | def generate_code() -> str: 5 | code = "".join([str(random.randint(0, 9)) for _ in range(4)]) 6 | return code 7 | 8 | 9 | def get_task_result(task_id: str, timeout: int = 10): 10 | from celery.result import AsyncResult 11 | 12 | task = AsyncResult(task_id) 13 | if task.ready(): 14 | return task.get(timeout=timeout) 15 | else: 16 | return None 17 | -------------------------------------------------------------------------------- /backend/src/categories/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | 5 | 6 | class Category(models.Model): 7 | id = models.AutoField( 8 | primary_key=True, 9 | editable=False, 10 | ) 11 | name = models.CharField( 12 | max_length=100, 13 | unique=True, 14 | null=False, 15 | blank=False, 16 | ) 17 | 18 | def __str__(self): 19 | return self.name 20 | -------------------------------------------------------------------------------- /backend/src/files/schemas.py: -------------------------------------------------------------------------------- 1 | from pydantic import ( 2 | BaseModel, 3 | ConfigDict, 4 | ) 5 | 6 | 7 | class AvatarSchema(BaseModel): 8 | avatar: str 9 | 10 | model_config = ConfigDict( 11 | json_schema_extra={ 12 | "description": "Avatar schema", 13 | "title": "AvatarSchema", 14 | "example": { 15 | "avatar": "https://example.com/avatar.png", 16 | }, 17 | }, 18 | ) 19 | -------------------------------------------------------------------------------- /frontend/src/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 | line-height: 1.5; 4 | font-weight: 400; 5 | 6 | font-synthesis: none; 7 | text-rendering: optimizeLegibility; 8 | -webkit-font-smoothing: antialiased; 9 | -moz-osx-font-smoothing: grayscale; 10 | } 11 | 12 | html, 13 | body { 14 | padding: 0; 15 | margin: 0; 16 | display: flex; 17 | flex-direction: column; 18 | min-height: 100%; 19 | } 20 | -------------------------------------------------------------------------------- /frontend/src/components/nav/ButtonLightDark.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "antd"; 2 | import { SunOutlined, MoonOutlined } from "@ant-design/icons"; 3 | import { useTheme } from "hooks/useTheme"; 4 | 5 | function ButtonLightDark() { 6 | const { theme, toggleTheme } = useTheme(); 7 | 8 | return ( 9 |