Update.
@ -1,24 +1,237 @@
|
||||
I want to start a online storage provider.
|
||||
On this site, people can:
|
||||
- register
|
||||
- login
|
||||
- see information about their storage quota
|
||||
- order storage (after logging in) using a slider. Price calculation must be available in config, price per gb and such.
|
||||
It must be built with:
|
||||
- aiohttp, jinja
|
||||
- vanilla js, vanilla css
|
||||
Important:
|
||||
- it must be a python package professionally structured
|
||||
- it must use the aiohttp class based views
|
||||
- it must host it's own frontend
|
||||
- it hosts the root entry point
|
||||
- javascript elements hould all extend from HTMLElement without shadowdom or shadowroot so they use the global css
|
||||
- javascript files must be in the ecmascript module way
|
||||
- structured css (css file per component)
|
||||
- templates must be structured very well
|
||||
- commercial business look and feel
|
||||
- all user information and configuration and such are in json file as backend. It should provide nice backend services mutating those files.
|
||||
- no database in exception of a very well structured json files
|
||||
- use as many files possible
|
||||
Excellent idea! Having detailed descriptions will be incredibly helpful for future design and development. I will go through each of the 8 screens we've generated for "Retoor's Cloud Solutions," incorporating the company name and providing comprehensive design guidelines.
|
||||
|
||||
---
|
||||
|
||||
### Detailed Design Descriptions for Retoor's Cloud Solutions Website
|
||||
|
||||
**Company Name:** Retoor's Cloud Solutions
|
||||
**Overall Design Philosophy:** Professional, Slick, Easy, Clear, Trustworthy.
|
||||
**Color Palette:** Predominantly clean blues, grays, and white. Teal/Cyan as an accent color for CTAs and interactive elements.
|
||||
**Typography:** Modern, legible sans-serif fonts (e.g., Montserrat, Open Sans, or similar) for headings and body text, ensuring clarity and a contemporary feel.
|
||||
**Imagery:** High-quality, professional stock photography or abstract digital art that conveys technology, collaboration, and security without being overly complex or distracting.
|
||||
**Icons:** Simple, outline-style icons with a consistent stroke weight, using the accent color for emphasis.
|
||||
**Layout:** Ample whitespace to prevent visual clutter, clear content hierarchy, and responsive design principles for various screen sizes (implied in the desktop mockups).
|
||||
|
||||
---
|
||||
|
||||
### Screen 1: Homepage - "Elevate Your Business Data"
|
||||
|
||||
**Purpose:** To immediately capture attention, communicate Retoor's core value proposition, and guide visitors towards key actions.
|
||||
|
||||
**Elements & Details:**
|
||||
|
||||
1. **Header/Navigation Bar:**
|
||||
* **Logo:** Top-left corner, "Retoor's Cloud Solutions" logo (e.g., a stylized "R" icon with the full text, maintaining the brand's professional look).
|
||||
* **Navigation Links:** Clear, concise links to "Solutions," "Pricing," "Security," "Support" in the top-right. These should be subtly styled text links, possibly changing color on hover.
|
||||
* **CTAs/Utility:** A prominent "Sign In" button (teal/cyan background, white text) and potentially an icon for a search bar or user profile (if logged in).
|
||||
|
||||
2. **Hero Section:**
|
||||
* **Headline:** Large, bold, and impactful: "Elevate Your Business Data. Securely. Collaborative." (Black or dark grey text).
|
||||
* **Sub-headline/Description:** Below the headline, a concise paragraph explaining Retoor's value: "Cloud storage solutions built for performance, reliability, and peace of mind." (Mid-grey text).
|
||||
* **Primary CTA (Button 1):** "Start Free Trial" (Teal/cyan background, white text, slightly rounded corners). This is the most prominent action.
|
||||
* **Secondary CTA (Button 2):** "Request Demo" (Outline button – white background, teal/cyan border and text, slightly rounded corners).
|
||||
* **Hero Image/Graphic:** A high-quality, professional image depicting business professionals collaborating around a laptop or tablet, conveying teamwork and modern office environments. The image should be integrated smoothly, possibly with a slight overlay or color tint that complements the brand palette.
|
||||
|
||||
3. **Below Hero - Key Benefits Section:**
|
||||
* **Section Title:** "Why Choose Retoor's?" (Prominent, dark grey text, centered or left-aligned).
|
||||
* **Benefit Modules (3 total):** Three distinct, equally spaced cards or sections.
|
||||
* Each module contains a simple, relevant icon (e.g., a shield for security, a globe for accessibility, chat bubbles for collaboration) rendered in the accent teal/cyan.
|
||||
* A concise, bold title (e.g., "Bank-Grade Security," "Global Accessibility," "Seamless Collaboration").
|
||||
* A brief, one-sentence description explaining the benefit (e.g., "Your data is encrypted end-to-end," "Access files anywhere, anytime, on any device," "Share, edit and co-author documents with ease.").
|
||||
* **Visual Style:** Cards should have a subtle drop shadow or clean border, white background, and be well-spaced.
|
||||
|
||||
---
|
||||
|
||||
### Screen 2: Solutions Page - "Tailored for Every Business Need"
|
||||
|
||||
**Purpose:** To showcase the versatility and specific applications of Retoor's Cloud Solutions for different business requirements.
|
||||
|
||||
**Elements & Details:**
|
||||
|
||||
1. **Header/Navigation Bar:** (Identical to Homepage header for consistency).
|
||||
|
||||
2. **Hero/Intro Section:**
|
||||
* **Headline:** Large, bold: "Tailored for Every Business Need" (Dark grey text).
|
||||
* **Sub-headline:** "Flexible cloud solutions for teams of all sizes" (Mid-grey text).
|
||||
|
||||
3. **Solutions Grid (6 Modules):**
|
||||
* **Layout:** A grid of six equally sized, card-like modules arranged in two rows of three.
|
||||
* **Each Module:**
|
||||
* **Icon:** A relevant, outline-style icon (e.g., file sharing icon, backup cloud icon, folders for collaboration, shield for security, bar chart for scalability) in the accent teal/cyan.
|
||||
* **Title:** Bold, descriptive title (e.g., "Secure File Sharing," "Automated Backup & Recovery," "Team Collaboration Spaces," "Enterprise-Grade Security," "Compliance Certifications," "Scalable Storage Plans").
|
||||
* **Description:** A short, benefit-focused paragraph detailing the solution. Examples: "Collaborate on documents and large files with colleagues and clients securely," "Protect critical business data with automated, daily easy-click recovery," "Organize important work documents, collaborate with teams, and access files for anywhere," "Benefit from advanced encryption and robust access controls," "Compliance certifications, and robust access controls," "Easily upgrade and downgrade storage as storage and team needs evolve."
|
||||
* **Visual Style:** Cards should have a clean, white background, subtle border or shadow, and generous padding for readability.
|
||||
|
||||
4. **Bottom CTA:**
|
||||
* **Button:** "Find Your Business Plan" (Teal/cyan background, white text, slightly rounded corners, centered below the grid).
|
||||
|
||||
---
|
||||
|
||||
### Screen 3: File Browser Interface - "Your Data, Organized and Accessible"
|
||||
|
||||
**Purpose:** To give users a clear and intuitive interface for managing their files and demonstrate the "easy and clear" aspect of Retoor's service.
|
||||
|
||||
**Elements & Details:**
|
||||
|
||||
1. **Header/Navigation Bar:** (Identical to public website header, but potentially with a different set of logged-in user specific links/icons instead of "Sign In").
|
||||
|
||||
2. **Dashboard Headline:** "Your Data, Organized and Accessible" (Dark grey, prominent).
|
||||
|
||||
3. **Main Layout:** A two-column layout:
|
||||
* **Left Sidebar (Navigation):**
|
||||
* **Section Title:** (Optional, or just icons).
|
||||
* **Menu Items:** "My Files," "Shared with me," "Recent," "Favorites," "Trash." Each with a corresponding icon (e.g., folder, shared icon, clock, star, trash can). These should be interactive, with a clear hover/active state (e.g., accent color background or text).
|
||||
* **Storage Quota Display:** At the bottom of the sidebar, a visual progress bar indicating storage used (e.g., "750GB / 1TB Used") in the accent teal/cyan, with remaining storage shown in grey.
|
||||
|
||||
* **Right Content Area (File List & Actions):**
|
||||
* **Search Bar:** Prominent search input field with a magnifying glass icon.
|
||||
* **Action Buttons:** A row of clear buttons for common actions: "+ New" (primary CTA, teal/cyan background), "Download," "Upload," "Share," "Delete" (icons for these actions).
|
||||
* **File List Table:**
|
||||
* **Columns:** "Name," "Last Modified," "Owner," "Size." These should be sortable (indicated by small up/down arrows next to column headers).
|
||||
* **Rows:** Each row represents a file or folder.
|
||||
* **Icon:** Small folder or file type icon next to the name.
|
||||
* **File Name:** (e.g., "Project X Brief.pdf," "Marketing_Campaign_03.zip").
|
||||
* **Details:** Corresponding "Last Modified," "Owner," and "Size" information.
|
||||
* **Action Ellipsis/Menu:** A small ellipsis or three-dot icon at the end of each row to reveal file-specific actions (e.g., rename, move, copy, preview).
|
||||
* **Contextual Details/Preview Pane (Optional, rightmost):** A smaller panel on the far right that could show details of a selected file, comments, or a quick preview. This reinforces the "easy and clear" aspect.
|
||||
|
||||
---
|
||||
|
||||
### Screen 4: Quota Management / Admin Dashboard - "Optimize Your Team's Storage"
|
||||
|
||||
**Purpose:** To provide administrators with a clear, visual overview and easy tools to manage storage quotas for their team or organization, reinforcing trustworthiness through transparency.
|
||||
|
||||
**Elements & Details:**
|
||||
|
||||
1. **Header/Navigation Bar:** (Consistent with logged-in user header).
|
||||
|
||||
2. **Dashboard Headline:** "Optimize Your Team's Storage" (Dark grey, prominent).
|
||||
* **Sub-headline:** "Flexible cloud monitoring for teams with ease."
|
||||
|
||||
3. **Layout:** Primarily a two-column layout.
|
||||
* **Left Column (Overview):**
|
||||
* **Total Storage Used (Donut Chart):** A prominent donut chart visually representing the "Total Storage Used:" (e.g., "750 GB / 1 TB"). The used portion should be in the accent teal/cyan, unused in light grey.
|
||||
* **Plan Details:** A smaller section below the chart outlining the current plan (e.g., "Business Plan," "TB Capacity," "Unlimited Users").
|
||||
|
||||
* **Right Column (User & Department Quotas):**
|
||||
* **Section Title:** "User & Department Quotas" (Clear and prominent).
|
||||
* **Add User Button:** "+ Add New User" (Teal/cyan background, white text, slightly rounded).
|
||||
* **User/Department List:** A scrollable list of users or departments, each presented as a clear row.
|
||||
* **Name:** User's name or department name (e.g., "John S," "Jane D," "Marketing Team").
|
||||
* **Storage Used/Quota:** Visual bar or text indicating storage used vs. allocated (e.g., "250 GB / 300 GB (75%)"). The used portion of the bar should be in the accent teal/cyan.
|
||||
* **Owner:** (Optional, if relevant for sub-departments).
|
||||
* **Quota Limit:** Text display of the specific quota for that user/department.
|
||||
* **Status/Actions:** Small icons or buttons for actions like "View Details," "Edit Quota," or "Delete User."
|
||||
* **"Set Quota" Button:** A prominent button at the bottom of the list for overall quota management, or adding a new quota. (Teal/cyan background, white text).
|
||||
|
||||
---
|
||||
|
||||
### Screen 5: Support Page - "We're Here to Help"
|
||||
|
||||
**Purpose:** To provide users with comprehensive support options, including self-service resources and direct contact methods, building trust and ensuring user satisfaction.
|
||||
|
||||
**Elements & Details:**
|
||||
|
||||
1. **Header/Navigation Bar:** (Identical to public website header).
|
||||
|
||||
2. **Hero/Intro Section:**
|
||||
* **Headline:** Large, bold: "We're Here to Help" (Dark grey text).
|
||||
* **Sub-headline:** "Flexible cloud solutions for all teams with ease." (Mid-grey text).
|
||||
|
||||
3. **Layout:** Two main sections: Knowledge Base and Contact Support.
|
||||
|
||||
4. **Knowledge Base Section (Left):**
|
||||
* **Section Title:** "Knowledge Base" (Prominent).
|
||||
* **Search Bar:** A large, clear search input field with a magnifying glass icon for users to find articles.
|
||||
* **Featured Articles/Categories (2-3 modules):**
|
||||
* Each module is a card-like box with an icon (e.g., gear for getting started, wrench for troubleshooting) in the accent teal/cyan.
|
||||
* **Category Title:** (e.g., "Getting Started Guides," "Troubleshooting Common Issues," "Security & Privacy FAQs").
|
||||
* **Bullet Points:** A few example articles or topics within that category (e.g., "How to upload your first files," "Resetting your password," "Understanding data encryption"). These should be clickable links.
|
||||
|
||||
5. **Contact Support Section (Right):**
|
||||
* **Section Title:** "Contact Support" (Prominent).
|
||||
* **Live Chat Option:**
|
||||
* **Icon:** Chat bubble icon in accent teal/cyan.
|
||||
* **Text:** "Live Chat"
|
||||
* **Button:** "Chat Now" (Teal/cyan background, white text, slightly rounded).
|
||||
* **Email Support Option:**
|
||||
* **Icon:** Email icon in accent teal/cyan.
|
||||
* **Text:** "Email Support"
|
||||
* **Button:** "Submit a Ticket" (Teal/cyan background, white text, slightly rounded).
|
||||
* **Phone Support Option:**
|
||||
* **Icon:** Phone icon in accent teal/cyan.
|
||||
* **Text:** "Phone Support"
|
||||
* **Number:** Clearly displayed phone number (e.g., "+00 77 5379 033").
|
||||
|
||||
---
|
||||
|
||||
### Screen 6: Use Cases Page - "Cloud Solutions for Every Industry & Challenge"
|
||||
|
||||
**Purpose:** To explicitly demonstrate the broad applicability of Retoor's Cloud Solutions across various business types and operational needs, helping potential clients envision how the service can benefit them.
|
||||
|
||||
**Elements & Details:**
|
||||
|
||||
1. **Header/Navigation Bar:** (Identical to public website header).
|
||||
|
||||
2. **Hero/Intro Section:**
|
||||
* **Headline:** Large, bold: "Cloud Solutions for Every Industry & Challenge" (Dark grey text).
|
||||
* **Sub-headline:** "Flexible cloud storage tailored to your needs." (Mid-grey text).
|
||||
|
||||
3. **Use Cases Grid (8 Modules):**
|
||||
* **Layout:** A grid of eight equally sized, card-like modules arranged in two rows of four.
|
||||
* **Each Module:**
|
||||
* **Icon:** A relevant, outline-style icon (e.g., network icon for collaboration, cloud with arrow for backup, user group for client portals, remote access icon, folder with lock for archiving) in the accent teal/cyan.
|
||||
* **Title:** Bold, descriptive title (e.g., "Secure File Collaboration," "Automated Data Backup," "Client & Partner Portals," "Remote Team Access," "Centralized Project Storage," "Remote Team Archiving," etc.).
|
||||
* **Description:** A short, benefit-focused paragraph detailing how Retoor's addresses this specific use case. Examples: "For marketing and creative teams to share large files and co-edit documents securely," "For consulting firms handling sensitive client data, ensure secure access and sharing," "For businesses with remote workforces needing seamless access to company files from anywhere."
|
||||
* **Visual Style:** Cards should have a clean, white background, subtle border or shadow, and generous padding for readability.
|
||||
|
||||
4. **Bottom CTA:**
|
||||
* **Button:** "Find Solutions For Your Team" (Teal/cyan background, white text, slightly rounded corners, centered below the grid).
|
||||
|
||||
---
|
||||
|
||||
### Screen 7: Login Page - "Access Your Retoor's Cloud Account"
|
||||
|
||||
**Purpose:** To provide a clear, secure, and easy-to-use entry point for existing users to access their Retoor's Cloud Solutions account.
|
||||
|
||||
**Elements & Details:**
|
||||
|
||||
1. **Header/Navigation Bar:** (Identical to public website header).
|
||||
|
||||
2. **Page Title:** Large, bold: "Access Your Retoor's Cloud Account" (Dark grey text).
|
||||
* **Sub-headline:** "Flexible cloud storage tailored to your needs." (Mid-grey text).
|
||||
|
||||
3. **Login Form Module (Centered):**
|
||||
* **Input Field 1:** "Email Address" (Standard input field with placeholder text).
|
||||
* **Input Field 2:** "Password" (Standard input field with placeholder text, possibly with a show/hide password toggle icon).
|
||||
* **Forgot Password Link:** "Forgot Password?" (Small text link, accent teal/cyan, to the right of the password field or below it).
|
||||
* **Login Button:** "Log In Securely" (Prominent, teal/cyan background, white text, slightly rounded corners).
|
||||
* **"Create an Account?" Link:** "Create an Account?" (Small text link, accent teal/cyan, below the login button, for new users).
|
||||
* **Visual Style:** The form should be contained within a clean, white card or panel, subtly centered on the page, with ample padding.
|
||||
|
||||
---
|
||||
|
||||
### Screen 8: Registration Page - "Create Your Retoor's Cloud Account"
|
||||
|
||||
**Purpose:** To offer a straightforward and clear process for new users to register for a Retoor's Cloud Solutions account, minimizing steps and confusion.
|
||||
|
||||
**Elements & Details:**
|
||||
|
||||
1. **Header/Navigation Bar:** (Identical to public website header).
|
||||
|
||||
2. **Page Title:** Large, bold: "Create Your Retoor's Cloud Account" (Dark grey text).
|
||||
* **Sub-headline:** "Unlock flexible cloud storage tailored to your needs." (Mid-grey text).
|
||||
|
||||
3. **Registration Form Module (Centered):**
|
||||
* **Input Field 1:** "Full Name" (Standard input field with placeholder text).
|
||||
* **Input Field 2:** "Work Email Address" (Standard input field with placeholder text).
|
||||
* **Input Field 3:** "Password" (Standard input field with placeholder text, possibly with a show/hide password toggle icon. Hint for strong password might be included here).
|
||||
* **Input Field 4:** "Confirm Password" (Standard input field with placeholder text).
|
||||
* **Terms & Privacy Checkbox:** "I agree to the Terms of Service & Privacy Policy" (Checkbox with a link to the respective policies, accent teal/cyan for the checkbox and link text).
|
||||
* **Create Account Button:** "Create Account" (Prominent, teal/cyan background, white text, slightly rounded corners).
|
||||
* **"Already have an account?" Link:** "Already have an account? Log In" (Small text link, accent teal/cyan, below the button, for existing users).
|
||||
* **Visual Style:** Similar to the Login Form, contained within a clean, white card or panel, subtly centered on the page, with ample padding.
|
||||
|
||||
---
|
||||
|
||||
These detailed descriptions should provide a solid foundation for designing and developing each page, ensuring a consistent and high-quality user experience for Retoor's Cloud Solutions.
|
||||
|
||||
@ -2,7 +2,6 @@ from aiohttp import web
|
||||
import aiohttp_jinja2
|
||||
import jinja2
|
||||
from pathlib import Path
|
||||
import aiohttp_session
|
||||
from aiohttp_session import setup as setup_session
|
||||
from aiohttp_session.cookie_storage import EncryptedCookieStorage
|
||||
import os
|
||||
@ -1,6 +1,5 @@
|
||||
from aiohttp import web
|
||||
from aiohttp_session import get_session
|
||||
import aiohttp_jinja2
|
||||
|
||||
|
||||
@web.middleware
|
||||
@ -17,7 +16,7 @@ async def user_middleware(request, handler):
|
||||
async def error_middleware(request, handler):
|
||||
try:
|
||||
return await handler(request)
|
||||
except web.HTTPException as ex:
|
||||
except web.HTTPException:
|
||||
raise # Re-raise HTTPException to see original traceback
|
||||
except Exception:
|
||||
raise # Re-raise generic Exception to see original traceback
|
||||
@ -1,7 +1,7 @@
|
||||
from pydantic import BaseModel, EmailStr, Field
|
||||
|
||||
class RegistrationModel(BaseModel):
|
||||
username: str = Field(min_length=3, max_length=50)
|
||||
full_name: str = Field(min_length=3, max_length=50)
|
||||
email: EmailStr
|
||||
password: str = Field(min_length=8)
|
||||
|
||||
@ -1,372 +0,0 @@
|
||||
:root {
|
||||
--primary-color: #0056b3; /* Retoor's Blue */
|
||||
--secondary-color: #6c757d; /* Retoor's Grey */
|
||||
--background-color: #ffffff; /* White background */
|
||||
--text-color: #202124; /* Dark grey text */
|
||||
--border-color: #dfe1e5; /* Light grey border */
|
||||
--button-bg-color: #f8f9fa; /* Light grey button background */
|
||||
--button-hover-bg-color: #f0f0f0; /* Slightly darker hover */
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-family: 'Roboto', Arial, sans-serif; /* Using a more modern font */
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.6; /* Improve readability */
|
||||
}
|
||||
|
||||
/* General typography */
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Card-like styling for sections */
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
padding: 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.retoors-container {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
max-width: 700px; /* Adjusted width for Retoor's */
|
||||
}
|
||||
|
||||
.retoors-logo {
|
||||
width: 200px; /* Adjusted width for Retoor's */
|
||||
height: 70px; /* Adjusted height for Retoor's */
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.search-bar-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 100%;
|
||||
padding: 10px 15px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 24px;
|
||||
font-size: 16px;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
transition: box-shadow 0.3s ease-in-out;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.search-input:focus {
|
||||
box-shadow: 0 1px 6px rgba(32,33,36,.28);
|
||||
border-color: rgba(223,225,229,0);
|
||||
}
|
||||
|
||||
.search-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.retoors-button {
|
||||
background-color: var(--button-bg-color);
|
||||
border: 1px solid var(--button-bg-color);
|
||||
border-radius: 4px;
|
||||
color: var(--text-color);
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
padding: 10px 15px;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
transition: background-color 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.retoors-button:hover {
|
||||
background-color: var(--button-hover-bg-color);
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
/* General styles for other pages to maintain consistency */
|
||||
main {
|
||||
max-width: 800px; /* Adjust for content pages */
|
||||
margin: 20px auto; /* Add some top margin for content pages */
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
display: inline-block;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #1765d3; /* Slightly darker blue */
|
||||
}
|
||||
|
||||
/* Form specific styles */
|
||||
.form-container {
|
||||
max-width: 400px;
|
||||
margin: 50px auto;
|
||||
/* Inherit card styles */
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.08); /* Slightly stronger shadow */
|
||||
padding: 2rem; /* Use card padding */
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.form-container h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 25px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: bold;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.form-group input[type="email"],
|
||||
.form-group input[type="password"],
|
||||
.form-group input[type="text"],
|
||||
.form-group input[type="number"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
box-sizing: border-box; /* Ensure padding doesn't increase width */
|
||||
}
|
||||
|
||||
.form-group input[type="email"]:focus,
|
||||
.form-group input[type="password"]:focus,
|
||||
.form-group input[type="text"]:focus,
|
||||
.form-group input[type="number"]:focus {
|
||||
border-color: var(--primary-color);
|
||||
box-shadow: 0 0 0 2px rgba(26, 115, 232, 0.2);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form-container .btn-primary {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-size: 18px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #dc3545;
|
||||
background-color: #f8d7da;
|
||||
border-color: #f5c6cb;
|
||||
padding: .75rem 1.25rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid transparent;
|
||||
border-radius: .25rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Dashboard specific styles */
|
||||
.dashboard-header {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.storage-overview {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.storage-gauge {
|
||||
background-color: #e9ecef;
|
||||
border-radius: .25rem;
|
||||
height: 20px;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.storage-gauge-bar {
|
||||
background-color: var(--primary-color);
|
||||
height: 100%;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
|
||||
.storage-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.9rem;
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
|
||||
.file-list table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.file-list th, .file-list td {
|
||||
padding: 0.75rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.file-list th {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.order-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.price-display {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
/* Custom Slider styles */
|
||||
custom-slider {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
custom-slider .slider-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
custom-slider input[type="range"] {
|
||||
flex-grow: 1;
|
||||
-webkit-appearance: none; /* Override default look */
|
||||
appearance: none;
|
||||
height: 8px;
|
||||
background: var(--border-color);
|
||||
outline: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
custom-slider input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: var(--primary-color);
|
||||
cursor: pointer;
|
||||
border: 2px solid #fff;
|
||||
box-shadow: 0 0 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
custom-slider input[type="range"]::-moz-range-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: var(--primary-color);
|
||||
cursor: pointer;
|
||||
border: 2px solid #fff;
|
||||
box-shadow: 0 0 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
custom-slider .slider-value {
|
||||
font-weight: bold;
|
||||
min-width: 50px; /* Ensure value doesn't jump around */
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 600px) {
|
||||
.retoors-logo {
|
||||
width: 150px; /* Adjusted for Retoor's */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.search-buttons {
|
||||
flex-direction: column;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.retoors-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 1rem;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.file-list th, .file-list td {
|
||||
padding: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
.form-container {
|
||||
max-width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: var(--border-radius);
|
||||
font-size: 1rem;
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
header {
|
||||
background-color: var(--container-bg-color);
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
padding: 1rem 2rem;
|
||||
border-bottom: 1px solid #EAEAEA;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
nav .logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
nav .logo img {
|
||||
height: 32px;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
text-decoration: none;
|
||||
color: var(--text-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
nav ul li a.btn-nav {
|
||||
background-color: #007BFF;
|
||||
color: white;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #007BFF;
|
||||
}
|
||||
|
||||
nav ul li a.btn-nav:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
<header>
|
||||
<nav>
|
||||
<a href="/" class="logo">
|
||||
<img src="/static/images/logo.svg" alt="HomeBase Storage" />
|
||||
<span>HomeBase Storage</span>
|
||||
</a>
|
||||
<ul>
|
||||
<li><a href="#">Features</a></li>
|
||||
<li><a href="#">Pricing</a></li>
|
||||
<li><a href="#">Reviews</a></li>
|
||||
<li><a href="#">Support</a></li>
|
||||
{% if request['user'] %}
|
||||
<li><a href="/dashboard">Dashboard</a></li>
|
||||
<li><a href="/logout" class="btn-nav">Logout</a></li>
|
||||
{% else %}
|
||||
<li><a href="/login">Login</a></li>
|
||||
<li><a href="/register" class="btn-nav">Start Your Free Trial</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
@ -1,71 +0,0 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="card">
|
||||
<section class="dashboard-header">
|
||||
<h2>Welcome, {{ user.email }}</h2>
|
||||
</section>
|
||||
|
||||
<section class="storage-overview">
|
||||
<h3>Storage Overview</h3>
|
||||
<div class="storage-gauge">
|
||||
<div class="storage-gauge-bar" style="width: {{ (user.storage_used_gb / user.storage_quota_gb) * 100 }}%;"></div>
|
||||
</div>
|
||||
<div class="storage-info">
|
||||
<span>{{ user.storage_used_gb }} GB used of {{ user.storage_quota_gb }} GB</span>
|
||||
<span>{{ ((user.storage_used_gb / user.storage_quota_gb) * 100)|round(2) }}%</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>My Files</h2>
|
||||
<div class="file-list">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
<th>Last Modified</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>documents.zip</td>
|
||||
<td>256 MB</td>
|
||||
<td>2025-11-08</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>photos.zip</td>
|
||||
<td>1.2 GB</td>
|
||||
<td>2025-11-07</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>project_alpha.zip</td>
|
||||
<td>512 MB</td>
|
||||
<td>2025-11-05</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Order More Storage</h2>
|
||||
<form action="/order" method="post" class="order-form">
|
||||
<div class="form-group">
|
||||
<label for="storage_amount">Storage (GB)</label>
|
||||
<custom-slider min="5" max="1000" value="{{ user.storage_quota_gb }}" step="5" name="storage_amount"></custom-slider>
|
||||
{% if errors.storage_amount %}
|
||||
<p class="error">{{ errors.storage_amount }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="price-display">
|
||||
<p>Price: <span id="price-display"></span></p>
|
||||
</div>
|
||||
<button type="submit" class="btn-primary">Order</button>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,8 +0,0 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<h1>404 - Page Not Found</h1>
|
||||
<p>The page you are looking for does not exist.</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -1,8 +0,0 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<h1>500 - Internal Server Error</h1>
|
||||
<p>Something went wrong on our end. Please try again later.</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -1,18 +0,0 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Retoor's Search{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="card">
|
||||
<div class="retoors-container">
|
||||
<img src="/static/images/retoors-logo.svg" alt="Retoor's" class="retoors-logo">
|
||||
<div class="search-bar-container">
|
||||
<input type="text" class="search-input" placeholder="Search Retoor's or type a URL">
|
||||
<div class="search-buttons">
|
||||
<button class="retoors-button">Retoor's Search</button>
|
||||
<button class="retoors-button">I'm Feeling Lucky</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,38 +0,0 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Welcome to Retoors Storage{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/components/index.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="card">
|
||||
<section class="hero">
|
||||
<h1>Solutions for Everyone</h1>
|
||||
<p>Securely store and manage your data with HomeBase Storage.</p>
|
||||
</section>
|
||||
|
||||
<section class="features">
|
||||
<div class="feature-card" id="families">
|
||||
<img src="/static/images/icon-families.svg" alt="Families Icon">
|
||||
<h2>For Families</h2>
|
||||
<p>Securely backup and share precious photos and videos. Keep memories safe for generations.</p>
|
||||
</div>
|
||||
<div class="feature-card" id="professionals">
|
||||
<img src="/static/images/icon-professionals.svg" alt="Professionals Icon">
|
||||
<h2>For Professionals</h2>
|
||||
<p>Organize important work documents, collaborate with teams, and access files from anywhere.</p>
|
||||
</div>
|
||||
<div class="feature-card" id="students">
|
||||
<img src="/static/images/icon-students.svg" alt="Students Icon">
|
||||
<h2>For Students</h2>
|
||||
<p>Store projects, notes, and research papers. Access study materials across your devices.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="cta">
|
||||
<a href="/register" class="btn-primary">Find Your Perfect Plan</a>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -1,29 +0,0 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Login{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form-container">
|
||||
<h2>Login to your Account</h2>
|
||||
{% if error %}
|
||||
<p class="error">{{ error }}</p>
|
||||
{% endif %}
|
||||
<form action="/login" method="post">
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" required>
|
||||
{% if errors.email %}
|
||||
<p class="error">{{ errors.email }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</.label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
{% if errors.password %}
|
||||
<p class="error">{{ errors.password }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<button type="submit" class="btn-primary">Login</button>
|
||||
</form>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@ -1,40 +0,0 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Register{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form-container">
|
||||
<h2>Create an Account</h2>
|
||||
{% if error %}
|
||||
<p class="error">{{ error }}</p>
|
||||
{% endif %}
|
||||
<form action="/register" method="post">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username" required>
|
||||
{% if errors.username %}
|
||||
<p class="error">{{ errors.username }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" required>
|
||||
{% if errors.email %}
|
||||
<p class="error">{{ errors.email }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
{% if errors.password %}
|
||||
<p class="error">{{ errors.password }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="confirm_password">Confirm Password</label>
|
||||
<input type="password" id="confirm_password" name="confirm_password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn-primary">Register</button>
|
||||
</form>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@ -7,5 +7,8 @@ def setup_routes(app):
|
||||
app.router.add_view("/register", RegistrationView, name="register")
|
||||
app.router.add_view("/logout", LogoutView, name="logout")
|
||||
app.router.add_view("/", SiteView, name="index")
|
||||
app.router.add_view("/solutions", SiteView, name="solutions")
|
||||
app.router.add_view("/support", SiteView, name="support")
|
||||
app.router.add_view("/use_cases", SiteView, name="use_cases")
|
||||
app.router.add_view("/dashboard", SiteView, name="dashboard")
|
||||
app.router.add_view("/order", OrderView, name="order")
|
||||
@ -21,13 +21,13 @@ class UserService:
|
||||
def get_user_by_email(self, email: str) -> Optional[Dict[str, Any]]:
|
||||
return next((user for user in self._users if user["email"] == email), None)
|
||||
|
||||
def create_user(self, username: str, email: str, password: str) -> Dict[str, Any]:
|
||||
def create_user(self, full_name: str, email: str, password: str) -> Dict[str, Any]:
|
||||
if self.get_user_by_email(email):
|
||||
raise ValueError("User with this email already exists")
|
||||
|
||||
hashed_password = hashlib.sha256(password.encode()).hexdigest()
|
||||
user = {
|
||||
"username": username,
|
||||
"full_name": full_name,
|
||||
"email": email,
|
||||
"password": hashed_password,
|
||||
"storage_quota_gb": 5, # Default quota
|
||||
481
retoors/static/css/base.css
Normal file
@ -0,0 +1,481 @@
|
||||
:root {
|
||||
--primary-color: #2196F3; /* Clean Blue */
|
||||
--accent-color: #00BCD4; /* Teal/Cyan */
|
||||
--secondary-color: #607D8B; /* Desaturated Blue-Grey */
|
||||
--background-color: #F5F5F5; /* Light Grey Background */
|
||||
--text-color: #263238; /* Dark Blue-Grey Text */
|
||||
--light-text-color: #757575; /* Lighter text for descriptions */
|
||||
--border-color: #CFD8DC; /* Light Grey Blue Border */
|
||||
--card-background: #FFFFFF; /* White for cards */
|
||||
--shadow-color: rgba(0, 0, 0, 0.08); /* Subtle shadow */
|
||||
|
||||
/* Button specific variables, using accent for primary CTAs */
|
||||
--btn-primary-bg: var(--accent-color);
|
||||
--btn-primary-text: #FFFFFF;
|
||||
--btn-primary-hover-bg: #00ACC1; /* Slightly darker teal */
|
||||
--btn-secondary-bg: #E0E0E0; /* Light grey for secondary buttons */
|
||||
--btn-secondary-text: var(--text-color);
|
||||
--btn-secondary-hover-bg: #BDBDBD; /* Darker grey for secondary hover */
|
||||
--btn-outline-border: var(--accent-color);
|
||||
--btn-outline-text: var(--accent-color);
|
||||
--btn-outline-hover-bg: rgba(0, 188, 212, 0.1); /* Light teal hover */
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-family: 'Roboto', sans-serif; /* Using a more modern font */
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.6; /* Improve readability */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* General typography */
|
||||
h1 {
|
||||
font-size: 2.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2.2rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.8rem;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.6rem;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1rem;
|
||||
color: var(--light-text-color);
|
||||
}
|
||||
|
||||
/* Card-like styling for sections */
|
||||
.card {
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--shadow-color);
|
||||
padding: 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column; /* Allow content to stack vertically */
|
||||
justify-content: flex-start; /* Align content to the top */
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
width: 100%; /* Ensure container takes full width */
|
||||
max-width: 1200px; /* Max width for overall content */
|
||||
margin: 0 auto; /* Center the container */
|
||||
}
|
||||
|
||||
.retoors-container {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
max-width: 700px; /* Adjusted width for Retoor's */
|
||||
margin-top: 50px; /* Add some top margin for content */
|
||||
}
|
||||
|
||||
.retoors-logo {
|
||||
width: 250px; /* Adjusted width for Retoor's */
|
||||
height: auto;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.search-bar-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 100%;
|
||||
max-width: 500px; /* Limit search input width */
|
||||
padding: 12px 20px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 24px;
|
||||
font-size: 16px;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
transition: box-shadow 0.3s ease-in-out, border-color 0.3s ease-in-out;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.search-input:focus {
|
||||
box-shadow: 0 1px 6px rgba(32,33,36,.28);
|
||||
border-color: var(--accent-color);
|
||||
}
|
||||
|
||||
.search-buttons {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.retoors-button {
|
||||
background-color: var(--btn-secondary-bg);
|
||||
border: 1px solid var(--btn-secondary-bg);
|
||||
border-radius: 4px;
|
||||
color: var(--btn-secondary-text);
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-size: 15px;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
transition: background-color 0.3s ease-in-out, border-color 0.3s ease-in-out, color 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.retoors-button:hover {
|
||||
background-color: var(--btn-secondary-hover-bg);
|
||||
border-color: var(--btn-secondary-hover-bg);
|
||||
}
|
||||
|
||||
/* General styles for other pages to maintain consistency */
|
||||
main {
|
||||
width: 100%;
|
||||
max-width: 960px; /* Adjust for content pages */
|
||||
margin: 40px auto; /* Add some top margin for content pages */
|
||||
padding: 0 20px; /* Add horizontal padding */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--accent-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
display: inline-block;
|
||||
background-color: var(--btn-primary-bg);
|
||||
color: var(--btn-primary-text);
|
||||
padding: 0.8rem 1.8rem;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: var(--btn-primary-hover-bg);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
display: inline-block;
|
||||
background-color: transparent;
|
||||
color: var(--btn-outline-text);
|
||||
border: 2px solid var(--btn-outline-border);
|
||||
padding: 0.8rem 1.8rem;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease-in-out, color 0.3s ease-in-out, border-color 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
background-color: var(--btn-outline-hover-bg);
|
||||
color: var(--btn-outline-text);
|
||||
border-color: var(--btn-outline-border);
|
||||
}
|
||||
|
||||
/* Form specific styles */
|
||||
.form-container {
|
||||
max-width: 450px;
|
||||
margin: 50px auto;
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 18px var(--shadow-color); /* Slightly stronger shadow */
|
||||
padding: 2.5rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.form-container h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
color: var(--text-color);
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
color: var(--text-color);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.form-group input[type="email"],
|
||||
.form-group input[type="password"],
|
||||
.form-group input[type="text"],
|
||||
.form-group input[type="number"] {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.form-group input[type="email"]:focus,
|
||||
.form-group input[type="password"]:focus,
|
||||
.form-group input[type="text"]:focus,
|
||||
.form-group input[type="number"]:focus {
|
||||
border-color: var(--accent-color);
|
||||
box-shadow: 0 0 0 3px rgba(0, 188, 212, 0.2);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form-container .btn-primary {
|
||||
width: 100%;
|
||||
padding: 14px;
|
||||
font-size: 18px;
|
||||
margin-top: 25px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #D32F2F; /* Red for errors */
|
||||
background-color: #FFEBEE; /* Light red background */
|
||||
border-color: #EF9A9A;
|
||||
padding: .75rem 1.25rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid transparent;
|
||||
border-radius: .25rem;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Dashboard specific styles */
|
||||
.dashboard-header {
|
||||
text-align: center;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.storage-overview {
|
||||
margin-bottom: 2.5rem;
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--shadow-color);
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.storage-gauge {
|
||||
background-color: var(--border-color);
|
||||
border-radius: .25rem;
|
||||
height: 20px;
|
||||
margin-bottom: 0.5rem;
|
||||
overflow: hidden; /* Ensure bar stays within bounds */
|
||||
}
|
||||
|
||||
.storage-gauge-bar {
|
||||
background-color: var(--accent-color);
|
||||
height: 100%;
|
||||
border-radius: .25rem;
|
||||
transition: width 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.storage-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.95rem;
|
||||
color: var(--light-text-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.file-list table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 1.5rem;
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--shadow-color);
|
||||
overflow: hidden; /* For rounded corners */
|
||||
}
|
||||
|
||||
.file-list th, .file-list td {
|
||||
padding: 1rem 1.5rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.file-list th {
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
font-weight: 700;
|
||||
font-size: 0.9rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.file-list td {
|
||||
color: var(--light-text-color);
|
||||
}
|
||||
|
||||
.file-list tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.order-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--shadow-color);
|
||||
padding: 2.5rem;
|
||||
max-width: 600px;
|
||||
margin: 40px auto;
|
||||
}
|
||||
|
||||
.price-display {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
margin-top: 1.5rem;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
/* Custom Slider styles */
|
||||
custom-slider {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
custom-slider .slider-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
custom-slider input[type="range"] {
|
||||
flex-grow: 1;
|
||||
-webkit-appearance: none; /* Override default look */
|
||||
appearance: none;
|
||||
height: 10px;
|
||||
background: var(--border-color);
|
||||
outline: none;
|
||||
border-radius: 5px;
|
||||
transition: background 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
custom-slider input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent-color);
|
||||
cursor: pointer;
|
||||
border: 3px solid var(--card-background);
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
transition: background-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
custom-slider input[type="range"]::-moz-range-thumb {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent-color);
|
||||
cursor: pointer;
|
||||
border: 3px solid var(--card-background);
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
transition: background-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
custom-slider .slider-value {
|
||||
font-weight: 700;
|
||||
min-width: 60px; /* Ensure value doesn't jump around */
|
||||
text-align: right;
|
||||
color: var(--text-color);
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
|
||||
/* Error Page Specific Styles */
|
||||
.error-page-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
padding: 50px 20px;
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 20px var(--shadow-color);
|
||||
max-width: 600px;
|
||||
margin: 50px auto;
|
||||
}
|
||||
|
||||
.error-page-container h1 {
|
||||
font-size: 3rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.error-page-container p {
|
||||
font-size: 1.2rem;
|
||||
color: var(--light-text-color);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.error-page-container .btn-primary {
|
||||
padding: 0.8rem 2rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.error-page-container h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
.error-page-container p {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.error-page-container h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.error-page-container p {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.error-page-container .btn-primary {
|
||||
padding: 0.7rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
217
retoors/static/css/components/dashboard.css
Normal file
@ -0,0 +1,217 @@
|
||||
/* Styles for the Dashboard (File Browser Interface) */
|
||||
|
||||
.dashboard-layout {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
align-items: flex-start; /* Align items to the top */
|
||||
}
|
||||
|
||||
.dashboard-sidebar {
|
||||
flex: 0 0 250px; /* Fixed width sidebar */
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--shadow-color);
|
||||
padding: 20px;
|
||||
position: sticky; /* Make sidebar sticky */
|
||||
top: 100px; /* Adjust based on header height */
|
||||
max-height: calc(100vh - 120px); /* Adjust based on header/footer */
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar-menu ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar-menu ul li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.sidebar-menu ul li a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 15px;
|
||||
border-radius: 5px;
|
||||
color: var(--text-color);
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.sidebar-menu ul li a:hover,
|
||||
.sidebar-menu ul li a.active {
|
||||
background-color: var(--accent-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.sidebar-menu ul li a img.icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 10px;
|
||||
filter: invert(30%) sepia(100%) saturate(2000%) hue-rotate(180deg) brightness(80%) contrast(100%); /* Example: change icon color */
|
||||
}
|
||||
|
||||
.sidebar-menu ul li a:hover img.icon,
|
||||
.sidebar-menu ul li a.active img.icon {
|
||||
filter: invert(100%) brightness(200%); /* Example: change icon color to white on hover/active */
|
||||
}
|
||||
|
||||
|
||||
.sidebar-storage-quota {
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.sidebar-storage-quota h4 {
|
||||
font-size: 1rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.dashboard-content {
|
||||
flex: 1;
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px var(--shadow-color);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.dashboard-content-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.dashboard-content-header h2 {
|
||||
margin: 0;
|
||||
font-size: 1.8rem;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.dashboard-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.dashboard-actions .btn-primary,
|
||||
.dashboard-actions .btn-outline {
|
||||
padding: 0.6rem 1.2rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.file-search-bar {
|
||||
width: 100%;
|
||||
padding: 10px 15px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 20px;
|
||||
font-size: 1rem;
|
||||
outline: none;
|
||||
margin-bottom: 20px;
|
||||
transition: border-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.file-search-bar:focus {
|
||||
border-color: var(--accent-color);
|
||||
box-shadow: 0 0 0 2px rgba(0, 188, 212, 0.2);
|
||||
}
|
||||
|
||||
.file-list-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.file-list-table th,
|
||||
.file-list-table td {
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.file-list-table th {
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.file-list-table td {
|
||||
color: var(--light-text-color);
|
||||
}
|
||||
|
||||
.file-list-table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.file-list-table .file-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
vertical-align: middle;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.file-list-table .action-ellipsis {
|
||||
cursor: pointer;
|
||||
font-size: 1.2rem;
|
||||
color: var(--light-text-color);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 992px) {
|
||||
.dashboard-layout {
|
||||
flex-direction: column;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.dashboard-sidebar {
|
||||
position: static; /* Remove sticky on smaller screens */
|
||||
flex: none;
|
||||
width: 100%;
|
||||
max-height: none;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.dashboard-content-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.dashboard-actions {
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.dashboard-actions .btn-primary,
|
||||
.dashboard-actions .btn-outline {
|
||||
flex: 1; /* Make buttons take equal width */
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.dashboard-layout {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.dashboard-sidebar {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.dashboard-content {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.file-list-table th,
|
||||
.file-list-table td {
|
||||
padding: 10px 12px;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
}
|
||||
1
retoors/static/css/components/form.css
Normal file
@ -0,0 +1 @@
|
||||
|
||||
160
retoors/static/css/components/index.css
Normal file
@ -0,0 +1,160 @@
|
||||
/* Styles for the Homepage (index.html) */
|
||||
|
||||
.hero-section {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
background-color: var(--card-background); /* White background for hero */
|
||||
margin-bottom: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 20px var(--shadow-color);
|
||||
position: relative;
|
||||
overflow: hidden; /* For potential background images */
|
||||
}
|
||||
|
||||
.hero-section h1 {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.hero-section p {
|
||||
font-size: 1.3rem;
|
||||
color: var(--light-text-color);
|
||||
max-width: 800px;
|
||||
margin: 0 auto 2.5rem auto;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.hero-ctas {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.hero-image-container {
|
||||
margin-top: 50px;
|
||||
/* Placeholder for a hero image */
|
||||
background-color: #ECEFF1; /* Light grey placeholder */
|
||||
height: 300px; /* Example height */
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--light-text-color);
|
||||
font-style: italic;
|
||||
font-size: 1.2rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-image-container img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.benefits-section {
|
||||
padding: 40px 20px;
|
||||
text-align: center;
|
||||
background-color: var(--background-color); /* Use overall background color */
|
||||
}
|
||||
|
||||
.benefits-section h2 {
|
||||
font-size: 2.5rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.benefits-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 30px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.benefit-card {
|
||||
background-color: var(--card-background);
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 15px var(--shadow-color);
|
||||
text-align: center;
|
||||
transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.benefit-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.benefit-card img.icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-bottom: 20px;
|
||||
color: var(--accent-color); /* Assuming SVG icons can inherit color */
|
||||
}
|
||||
|
||||
.benefit-card h3 {
|
||||
font-size: 1.5rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.benefit-card p {
|
||||
font-size: 1rem;
|
||||
color: var(--light-text-color);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Responsive adjustments for index.css */
|
||||
@media (max-width: 992px) {
|
||||
.hero-section h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
.hero-section p {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.benefits-section h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-section {
|
||||
padding: 40px 15px;
|
||||
}
|
||||
.hero-section h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
.hero-section p {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.hero-ctas {
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
.benefits-grid {
|
||||
grid-template-columns: 1fr; /* Stack cards on small screens */
|
||||
}
|
||||
.benefit-card {
|
||||
padding: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.hero-section h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.hero-section p {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.hero-ctas .btn-primary, .hero-ctas .btn-outline {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.benefits-section h2 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
}
|
||||
78
retoors/static/css/components/login.css
Normal file
@ -0,0 +1,78 @@
|
||||
/* Styles for the Login Page */
|
||||
|
||||
.login-page-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: calc(100vh - 120px); /* Adjust based on header/footer height */
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.login-page-container h1 {
|
||||
font-size: 2.5rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-page-container .subtitle {
|
||||
font-size: 1.1rem;
|
||||
color: var(--light-text-color);
|
||||
margin-bottom: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
max-width: 450px; /* Adjust as needed */
|
||||
width: 100%;
|
||||
padding: 2.5rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.forgot-password-link {
|
||||
display: block;
|
||||
text-align: right;
|
||||
margin-top: -10px; /* Adjust to align with password field */
|
||||
margin-bottom: 20px;
|
||||
font-size: 0.9rem;
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.forgot-password-link:hover {
|
||||
color: var(--accent-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.create-account-link {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
font-size: 0.95rem;
|
||||
color: var(--light-text-color);
|
||||
}
|
||||
|
||||
.create-account-link a {
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.create-account-link a:hover {
|
||||
color: var(--accent-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 600px) {
|
||||
.login-page-container h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.login-page-container .subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.form-container {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
123
retoors/static/css/components/navigation.css
Normal file
@ -0,0 +1,123 @@
|
||||
header {
|
||||
background-color: var(--card-background); /* Use card background for header */
|
||||
box-shadow: 0 2px 4px var(--shadow-color);
|
||||
padding: 1rem 2rem;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
position: sticky; /* Make header sticky */
|
||||
top: 0;
|
||||
z-index: 1000; /* Ensure header is above other content */
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
nav .logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
color: var(--text-color); /* Use text color for logo text */
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
nav .logo img {
|
||||
height: 36px; /* Slightly larger logo */
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
margin-left: 1.8rem; /* Adjust spacing */
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
text-decoration: none;
|
||||
color: var(--light-text-color); /* Use light text color for nav links */
|
||||
font-weight: 500;
|
||||
transition: color 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
nav ul li a:hover {
|
||||
color: var(--accent-color); /* Accent color on hover */
|
||||
}
|
||||
|
||||
/* New button styles for navigation */
|
||||
nav ul li a.btn-primary-nav {
|
||||
background-color: var(--btn-primary-bg);
|
||||
color: var(--btn-primary-text);
|
||||
padding: 0.6rem 1.2rem;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
nav ul li a.btn-primary-nav:hover {
|
||||
background-color: var(--btn-primary-hover-bg);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
nav ul li a.btn-outline-nav {
|
||||
background-color: transparent;
|
||||
color: var(--btn-outline-text);
|
||||
border: 2px solid var(--btn-outline-border);
|
||||
padding: 0.6rem 1.2rem;
|
||||
border-radius: 5px;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.3s ease-in-out, color 0.3s ease-in-out, border-color 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
nav ul li a.btn-outline-nav:hover {
|
||||
background-color: var(--btn-outline-hover-bg);
|
||||
color: var(--btn-outline-text);
|
||||
border-color: var(--btn-outline-border);
|
||||
}
|
||||
|
||||
/* Responsive adjustments for navigation */
|
||||
@media (max-width: 768px) {
|
||||
nav {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
nav .logo {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
margin: 0.5rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
display: block;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
nav ul li a.btn-primary-nav,
|
||||
nav ul li a.btn-outline-nav {
|
||||
display: block;
|
||||
text-align: center;
|
||||
width: calc(100% - 2.4rem); /* Account for padding */
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
281
retoors/static/css/components/order.css
Normal file
@ -0,0 +1,281 @@
|
||||
/* Styles for the Quota Management / Admin Dashboard (order.html) */
|
||||
|
||||
.order-management-layout {
|
||||
padding: 40px 20px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.quota-overview-card {
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 20px var(--shadow-color);
|
||||
padding: 30px;
|
||||
margin-bottom: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.quota-overview-card h2 {
|
||||
font-size: 2.5rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.quota-overview-card .subtitle {
|
||||
font-size: 1.1rem;
|
||||
color: var(--light-text-color);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.overview-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||
gap: 30px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.total-storage-chart {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
background-color: var(--background-color); /* Lighter background for this section */
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.total-storage-chart h3 {
|
||||
font-size: 1.3rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.donut-chart-container {
|
||||
position: relative;
|
||||
width: 180px; /* Size of the "donut" */
|
||||
height: 180px;
|
||||
margin: 0 auto 20px auto;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(var(--accent-color) 0% {{ (user.storage_used_gb / user.storage_quota_gb) * 100 }}%, var(--border-color) {{ (user.storage_used_gb / user.storage_quota_gb) * 100 }}% 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.donut-chart-container::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background: var(--card-background);
|
||||
width: 140px; /* Inner circle size */
|
||||
height: 140px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.donut-chart-text {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.donut-chart-text .used-gb {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.donut-chart-text .total-gb {
|
||||
color: var(--light-text-color);
|
||||
}
|
||||
|
||||
|
||||
.plan-details {
|
||||
font-size: 0.95rem;
|
||||
color: var(--light-text-color);
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.order-form-card {
|
||||
background-color: var(--background-color);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||
padding: 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.order-form-card h3 {
|
||||
font-size: 1.3rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.order-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.order-form .form-group label {
|
||||
font-weight: 600;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.order-form .price-display {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent-color);
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.order-form .btn-primary {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.user-quotas-section {
|
||||
background-color: var(--card-background);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 20px var(--shadow-color);
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.user-quotas-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30px;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.user-quotas-header h2 {
|
||||
font-size: 2rem;
|
||||
color: var(--text-color);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.user-quotas-header .btn-primary {
|
||||
padding: 0.7rem 1.5rem;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.user-quota-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.user-quota-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
.user-quota-item .user-info h4 {
|
||||
font-size: 1.2rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.user-quota-item .user-info p {
|
||||
font-size: 0.9rem;
|
||||
color: var(--light-text-color);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.user-quota-item .quota-details {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.user-quota-item .quota-details p {
|
||||
font-size: 0.95rem;
|
||||
color: var(--light-text-color);
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.user-quota-item .quota-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.user-quota-item .quota-actions .btn-outline {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* Small storage gauge for user items */
|
||||
.storage-gauge.small {
|
||||
height: 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.storage-gauge.large {
|
||||
height: 15px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 992px) {
|
||||
.overview-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.user-quotas-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.user-quotas-header .btn-primary {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.order-management-layout {
|
||||
padding: 20px 15px;
|
||||
}
|
||||
.quota-overview-card h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.quota-overview-card .subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.user-quotas-header h2 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
.user-quota-list {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.quota-overview-card {
|
||||
padding: 20px;
|
||||
}
|
||||
.quota-overview-card h2 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
.donut-chart-container {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.donut-chart-container::before {
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
}
|
||||
.donut-chart-text {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.order-form-card {
|
||||
padding: 20px;
|
||||
}
|
||||
.user-quotas-section {
|
||||
padding: 20px;
|
||||
}
|
||||
.user-quotas-header h2 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
89
retoors/static/css/components/register.css
Normal file
@ -0,0 +1,89 @@
|
||||
/* Styles for the Registration Page */
|
||||
|
||||
.register-page-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: calc(100vh - 120px); /* Adjust based on header/footer height */
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.register-page-container h1 {
|
||||
font-size: 2.5rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.register-page-container .subtitle {
|
||||
font-size: 1.1rem;
|
||||
color: var(--light-text-color);
|
||||
margin-bottom: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
max-width: 450px; /* Adjust as needed */
|
||||
width: 100%;
|
||||
padding: 2.5rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.terms-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 0.95rem;
|
||||
color: var(--light-text-color);
|
||||
}
|
||||
|
||||
.terms-checkbox input[type="checkbox"] {
|
||||
margin-right: 10px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
accent-color: var(--accent-color); /* Style checkbox with accent color */
|
||||
}
|
||||
|
||||
.terms-checkbox a {
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.terms-checkbox a:hover {
|
||||
color: var(--accent-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.login-link {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
font-size: 0.95rem;
|
||||
color: var(--light-text-color);
|
||||
}
|
||||
|
||||
.login-link a {
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.login-link a:hover {
|
||||
color: var(--accent-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 600px) {
|
||||
.register-page-container h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.register-page-container .subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.form-container {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
113
retoors/static/css/components/solutions.css
Normal file
@ -0,0 +1,113 @@
|
||||
/* Styles for the Solutions Page */
|
||||
|
||||
.solutions-hero {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
background-color: var(--card-background);
|
||||
margin-bottom: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 20px var(--shadow-color);
|
||||
}
|
||||
|
||||
.solutions-hero h1 {
|
||||
font-size: 3.2rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.solutions-hero p {
|
||||
font-size: 1.2rem;
|
||||
color: var(--light-text-color);
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.solutions-grid-section {
|
||||
padding: 40px 20px;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
.solutions-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 30px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.solution-card {
|
||||
background-color: var(--card-background);
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 15px var(--shadow-color);
|
||||
text-align: center;
|
||||
transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.solution-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.solution-card img.icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-bottom: 20px;
|
||||
color: var(--accent-color); /* Assuming SVG icons can inherit color */
|
||||
}
|
||||
|
||||
.solution-card h3 {
|
||||
font-size: 1.5rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.solution-card p {
|
||||
font-size: 1rem;
|
||||
color: var(--light-text-color);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.cta-bottom {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 992px) {
|
||||
.solutions-hero h1 {
|
||||
font-size: 2.8rem;
|
||||
}
|
||||
.solutions-hero p {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.solutions-hero {
|
||||
padding: 40px 15px;
|
||||
}
|
||||
.solutions-hero h1 {
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
.solutions-hero p {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.solutions-grid {
|
||||
grid-template-columns: 1fr; /* Stack cards on small screens */
|
||||
}
|
||||
.solution-card {
|
||||
padding: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.solutions-hero h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
.solutions-hero p {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
187
retoors/static/css/components/support.css
Normal file
@ -0,0 +1,187 @@
|
||||
/* Styles for the Support Page */
|
||||
|
||||
.support-hero {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
background-color: var(--card-background);
|
||||
margin-bottom: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 20px var(--shadow-color);
|
||||
}
|
||||
|
||||
.support-hero h1 {
|
||||
font-size: 3.2rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.support-hero p {
|
||||
font-size: 1.2rem;
|
||||
color: var(--light-text-color);
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.support-content-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr; /* Knowledge Base wider than Contact Support */
|
||||
gap: 30px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.knowledge-base-section {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.knowledge-base-section h2 {
|
||||
font-size: 2rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.knowledge-base-section .search-input {
|
||||
width: 100%;
|
||||
max-width: none; /* Override base.css max-width */
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.featured-articles {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.article-category {
|
||||
background-color: var(--background-color);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||
padding: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.article-category img.icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-bottom: 15px;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.article-category h3 {
|
||||
font-size: 1.3rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.article-category ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.article-category ul li {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.article-category ul li a {
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.article-category ul li a:hover {
|
||||
text-decoration: underline;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.contact-support-section {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.contact-support-section h2 {
|
||||
font-size: 2rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.contact-option {
|
||||
background-color: var(--background-color);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.contact-option img.icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-bottom: 15px;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.contact-option h3 {
|
||||
font-size: 1.4rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.contact-option p {
|
||||
font-size: 0.95rem;
|
||||
color: var(--light-text-color);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.contact-option .btn-primary {
|
||||
width: 100%;
|
||||
padding: 0.8rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.contact-option .phone-number {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 992px) {
|
||||
.support-content-grid {
|
||||
grid-template-columns: 1fr; /* Stack columns on smaller screens */
|
||||
}
|
||||
.knowledge-base-section, .contact-support-section {
|
||||
padding: 20px;
|
||||
}
|
||||
.featured-articles {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.support-hero h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
.support-hero p {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
.knowledge-base-section h2, .contact-support-section h2 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.support-hero h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.support-hero p {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.article-category h3 {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
.contact-option h3 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
}
|
||||
113
retoors/static/css/components/use_cases.css
Normal file
@ -0,0 +1,113 @@
|
||||
/* Styles for the Use Cases Page */
|
||||
|
||||
.use-cases-hero {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
background-color: var(--card-background);
|
||||
margin-bottom: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 20px var(--shadow-color);
|
||||
}
|
||||
|
||||
.use-cases-hero h1 {
|
||||
font-size: 3.2rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.use-cases-hero p {
|
||||
font-size: 1.2rem;
|
||||
color: var(--light-text-color);
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.use-cases-grid-section {
|
||||
padding: 40px 20px;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
.use-cases-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 30px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.use-case-card {
|
||||
background-color: var(--card-background);
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 15px var(--shadow-color);
|
||||
text-align: center;
|
||||
transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.use-case-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.use-case-card img.icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-bottom: 20px;
|
||||
color: var(--accent-color); /* Assuming SVG icons can inherit color */
|
||||
}
|
||||
|
||||
.use-case-card h3 {
|
||||
font-size: 1.5rem;
|
||||
color: var(--text-color);
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.use-case-card p {
|
||||
font-size: 1rem;
|
||||
color: var(--light-text-color);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.cta-bottom {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 992px) {
|
||||
.use-cases-hero h1 {
|
||||
font-size: 2.8rem;
|
||||
}
|
||||
.use-cases-hero p {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.use-cases-hero {
|
||||
padding: 40px 15px;
|
||||
}
|
||||
.use-cases-hero h1 {
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
.use-cases-hero p {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.use-cases-grid {
|
||||
grid-template-columns: 1fr; /* Stack cards on small screens */
|
||||
}
|
||||
.use-case-card {
|
||||
padding: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.use-cases-hero h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
.use-cases-hero p {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 396 B After Width: | Height: | Size: 396 B |
|
Before Width: | Height: | Size: 469 B After Width: | Height: | Size: 469 B |
|
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 321 B |
|
Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 200 B |
|
Before Width: | Height: | Size: 701 B After Width: | Height: | Size: 701 B |
21
retoors/templates/components/navigation.html
Normal file
@ -0,0 +1,21 @@
|
||||
<header>
|
||||
<nav>
|
||||
<a href="/" class="logo">
|
||||
<img src="/static/images/retoors-logo.svg" alt="Retoor's Cloud Solutions" />
|
||||
<span>Retoor's Cloud Solutions</span>
|
||||
</a>
|
||||
<ul>
|
||||
<li><a href="/solutions">Solutions</a></li>
|
||||
<li><a href="/pricing">Pricing</a></li>
|
||||
<li><a href="/security">Security</a></li>
|
||||
<li><a href="/support">Support</a></li>
|
||||
{% if request['user'] %}
|
||||
<li><a href="/dashboard">Dashboard</a></li>
|
||||
<li><a href="/logout" class="btn-nav">Logout</a></li>
|
||||
{% else %}
|
||||
<li><a href="/login" class="btn-outline-nav">Sign In</a></li>
|
||||
<li><a href="/register" class="btn-primary-nav">Start Your Free Trial</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
87
retoors/templates/pages/dashboard.html
Normal file
@ -0,0 +1,87 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Dashboard - Retoor's Cloud Solutions{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/components/dashboard.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="dashboard-layout">
|
||||
<aside class="dashboard-sidebar">
|
||||
<div class="sidebar-menu">
|
||||
<ul>
|
||||
<li><a href="#" class="active"><img src="/static/images/icon-families.svg" alt="My Files Icon" class="icon"> My Files</a></li> {# Placeholder icon #}
|
||||
<li><a href="#"><img src="/static/images/icon-professionals.svg" alt="Shared Icon" class="icon"> Shared with me</a></li> {# Placeholder icon #}
|
||||
<li><a href="#"><img src="/static/images/icon-students.svg" alt="Recent Icon" class="icon"> Recent</a></li> {# Placeholder icon #}
|
||||
<li><a href="#"><img src="/static/images/icon-families.svg" alt="Favorites Icon" class="icon"> Favorites</a></li> {# Placeholder icon #}
|
||||
<li><a href="#"><img src="/static/images/icon-professionals.svg" alt="Trash Icon" class="icon"> Trash</a></li> {# Placeholder icon #}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-storage-quota">
|
||||
<h4>Storage Used</h4>
|
||||
<div class="storage-gauge">
|
||||
<div class="storage-gauge-bar" style="width: {{ (user.storage_used_gb / user.storage_quota_gb) * 100 }}%;"></div>
|
||||
</div>
|
||||
<div class="storage-info">
|
||||
<span>{{ user.storage_used_gb }} GB used of {{ user.storage_quota_gb }} GB</span>
|
||||
<span>{{ ((user.storage_used_gb / user.storage_quota_gb) * 100)|round(2) }}%</span>
|
||||
</div>
|
||||
<a href="/order" class="btn-primary" style="margin-top: 20px; display: block; text-align: center;">Manage Quota</a>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<section class="dashboard-content">
|
||||
<div class="dashboard-content-header">
|
||||
<h2>Your Data, Organized and Accessible</h2>
|
||||
<div class="dashboard-actions">
|
||||
<button class="btn-primary">+ New</button>
|
||||
<button class="btn-outline">Download</button>
|
||||
<button class="btn-outline">Upload</button>
|
||||
<button class="btn-outline">Share</button>
|
||||
<button class="btn-outline">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="text" class="file-search-bar" placeholder="Search your files...">
|
||||
|
||||
<div class="file-list-table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Owner</th>
|
||||
<th>Last Modified</th>
|
||||
<th>Size</th>
|
||||
<th></th> {# For action ellipsis #}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><img src="/static/images/icon-families.svg" alt="Folder Icon" class="file-icon"> documents.zip</td> {# Placeholder icon #}
|
||||
<td>{{ user.email }}</td>
|
||||
<td>2025-11-08</td>
|
||||
<td>256 MB</td>
|
||||
<td><span class="action-ellipsis">...</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/static/images/icon-professionals.svg" alt="File Icon" class="file-icon"> photos.zip</td> {# Placeholder icon #}
|
||||
<td>{{ user.email }}</td>
|
||||
<td>2025-11-07</td>
|
||||
<td>1.2 GB</td>
|
||||
<td><span class="action-ellipsis">...</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="/static/images/icon-students.svg" alt="File Icon" class="file-icon"> project_alpha.zip</td> {# Placeholder icon #}
|
||||
<td>{{ user.email }}</td>
|
||||
<td>2025-11-05</td>
|
||||
<td>512 MB</td>
|
||||
<td><span class="action-ellipsis">...</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
11
retoors/templates/pages/errors/404.html
Normal file
@ -0,0 +1,11 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}404 Not Found - Retoor's Cloud Solutions{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="error-page-container">
|
||||
<h1>404 - Page Not Found</h1>
|
||||
<p>Oops! The page you're looking for doesn't exist or has been moved.</p>
|
||||
<a href="/" class="btn-primary">Go to Homepage</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
11
retoors/templates/pages/errors/500.html
Normal file
@ -0,0 +1,11 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}500 Internal Server Error - Retoor's Cloud Solutions{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="error-page-container">
|
||||
<h1>500 - Internal Server Error</h1>
|
||||
<p>Something went wrong on our end. We're working to fix it. Please try again later.</p>
|
||||
<a href="/" class="btn-primary">Go to Homepage</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
45
retoors/templates/pages/index.html
Normal file
@ -0,0 +1,45 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Elevate Your Business Data - Retoor's Cloud Solutions{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/components/index.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main>
|
||||
<section class="hero-section">
|
||||
<h1>Elevate Your Business Data. Securely. Collaborative.</h1>
|
||||
<p>Cloud storage solutions built for performance, reliability, and peace of mind.</p>
|
||||
<div class="hero-ctas">
|
||||
<a href="/register" class="btn-primary">Start Free Trial</a>
|
||||
<a href="/contact" class="btn-outline">Request Demo</a> {# Assuming a /contact page for demo requests #}
|
||||
</div>
|
||||
<div class="hero-image-container">
|
||||
{# Placeholder for a high-quality, professional image depicting business professionals collaborating #}
|
||||
<img src="/static/images/example.jpg" alt="Business professionals collaborating with Retoor's Cloud Solutions">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="benefits-section">
|
||||
<h2>Why Choose Retoor's?</h2>
|
||||
<div class="benefits-grid">
|
||||
<div class="benefit-card">
|
||||
<img src="/static/images/icon-families.svg" alt="Security Icon" class="icon"> {# Reusing existing icon, ideally would be a shield #}
|
||||
<h3>Bank-Grade Security</h3>
|
||||
<p>Your data is encrypted end-to-end, ensuring maximum protection and privacy.</p>
|
||||
</div>
|
||||
<div class="benefit-card">
|
||||
<img src="/static/images/icon-professionals.svg" alt="Accessibility Icon" class="icon"> {# Reusing existing icon, ideally would be a globe #}
|
||||
<h3>Global Accessibility</h3>
|
||||
<p>Access files anywhere, anytime, on any device with seamless synchronization.</p>
|
||||
</div>
|
||||
<div class="benefit-card">
|
||||
<img src="/static/images/icon-students.svg" alt="Collaboration Icon" class="icon"> {# Reusing existing icon, ideally would be chat bubbles #}
|
||||
<h3>Seamless Collaboration</h3>
|
||||
<p>Share, edit, and co-author documents with ease, boosting team productivity.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
40
retoors/templates/pages/login.html
Normal file
@ -0,0 +1,40 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Access Your Retoor's Cloud Account{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/components/login.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="login-page-container">
|
||||
<h1>Access Your Retoor's Cloud Account</h1>
|
||||
<p class="subtitle">Flexible cloud storage tailored to your needs.</p>
|
||||
|
||||
<section class="form-container">
|
||||
<h2>Login to your Account</h2>
|
||||
{% if error %}
|
||||
<p class="error">{{ error }}</p>
|
||||
{% endif %}
|
||||
<form action="/login" method="post">
|
||||
<div class="form-group">
|
||||
<label for="email">Email Address</label>
|
||||
<input type="email" id="email" name="email" required value="{{ data.email or '' }}">
|
||||
{% if errors.email %}
|
||||
<p class="error">{{ errors.email }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
{% if errors.password %}
|
||||
<p class="error">{{ errors.password }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<a href="#" class="forgot-password-link">Forgot Password?</a>
|
||||
<button type="submit" class="btn-primary">Log In Securely</button>
|
||||
</form>
|
||||
<p class="create-account-link">Don't have an account? <a href="/register">Create an Account</a></p>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
||||
107
retoors/templates/pages/order.html
Normal file
@ -0,0 +1,107 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Quota Management - Retoor's Cloud Solutions{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/components/order.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="order-management-layout">
|
||||
<section class="quota-overview-card">
|
||||
<h2>Optimize Your Team's Storage</h2>
|
||||
<p class="subtitle">Flexible cloud monitoring for teams with ease.</p>
|
||||
|
||||
<div class="overview-grid">
|
||||
<div class="total-storage-chart">
|
||||
<h3>Total Storage Used:</h3>
|
||||
<div class="donut-chart-container">
|
||||
{# Placeholder for a donut chart. For simplicity, we'll use text for now. #}
|
||||
<div class="donut-chart-text">
|
||||
<span class="used-gb">{{ user.storage_used_gb }} GB</span> / <span class="total-gb">{{ user.storage_quota_gb }} GB</span>
|
||||
</div>
|
||||
<div class="storage-gauge large">
|
||||
<div class="storage-gauge-bar" style="width: {{ (user.storage_used_gb / user.storage_quota_gb) * 100 }}%;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="plan-details">Current Plan: Business Plan ({{ user.storage_quota_gb }} GB Capacity, Unlimited Users)</p>
|
||||
</div>
|
||||
|
||||
<div class="order-form-card">
|
||||
<h3>Adjust Your Quota</h3>
|
||||
<form action="/order" method="post" class="order-form">
|
||||
<div class="form-group">
|
||||
<label for="storage_amount">Storage (GB)</label>
|
||||
<custom-slider min="5" max="1000" value="{{ user.storage_quota_gb }}" step="5" name="storage_amount"></custom-slider>
|
||||
{% if errors.storage_amount %}
|
||||
<p class="error">{{ errors.storage_amount }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="price-display">
|
||||
<p>Estimated Price: <span id="price-display"></span></p>
|
||||
</div>
|
||||
<button type="submit" class="btn-primary">Update Quota</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="user-quotas-section">
|
||||
<div class="user-quotas-header">
|
||||
<h2>User & Department Quotas</h2>
|
||||
<button class="btn-primary">+ Add New User</button>
|
||||
</div>
|
||||
<div class="user-quota-list">
|
||||
{# Example User/Department Quota #}
|
||||
<div class="user-quota-item card">
|
||||
<div class="user-info">
|
||||
<h4>John S.</h4>
|
||||
<p>john.s@retoors.com</p>
|
||||
</div>
|
||||
<div class="quota-details">
|
||||
<div class="storage-gauge small">
|
||||
<div class="storage-gauge-bar" style="width: 75%;"></div> {# Example value #}
|
||||
</div>
|
||||
<p>225 GB / 300 GB (75%)</p>
|
||||
</div>
|
||||
<div class="quota-actions">
|
||||
<button class="btn-outline">Edit Quota</button>
|
||||
<button class="btn-outline">Delete User</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-quota-item card">
|
||||
<div class="user-info">
|
||||
<h4>Marketing Team</h4>
|
||||
<p>marketing@retoors.com</p>
|
||||
</div>
|
||||
<div class="quota-details">
|
||||
<div class="storage-gauge small">
|
||||
<div class="storage-gauge-bar" style="width: 50%;"></div> {# Example value #}
|
||||
</div>
|
||||
<p>500 GB / 1 TB (50%)</p>
|
||||
</div>
|
||||
<div class="quota-actions">
|
||||
<button class="btn-outline">Edit Quota</button>
|
||||
<button class="btn-outline">Delete Team</button>
|
||||
</div>
|
||||
</div>
|
||||
{# Current user's quota #}
|
||||
<div class="user-quota-item card">
|
||||
<div class="user-info">
|
||||
<h4>{{ user.email }} (You)</h4>
|
||||
<p>Individual Quota</p>
|
||||
</div>
|
||||
<div class="quota-details">
|
||||
<div class="storage-gauge small">
|
||||
<div class="storage-gauge-bar" style="width: {{ (user.storage_used_gb / user.storage_quota_gb) * 100 }}%;"></div>
|
||||
</div>
|
||||
<p>{{ user.storage_used_gb }} GB / {{ user.storage_quota_gb }} GB ({{ ((user.storage_used_gb / user.storage_quota_gb) * 100)|round(2) }}%)</p>
|
||||
</div>
|
||||
<div class="quota-actions">
|
||||
<button class="btn-outline">View Details</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
57
retoors/templates/pages/register.html
Normal file
@ -0,0 +1,57 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Create Your Retoor's Cloud Account{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/components/register.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="register-page-container">
|
||||
<h1>Create Your Retoor's Cloud Account</h1>
|
||||
<p class="subtitle">Unlock flexible cloud storage tailored to your needs.</p>
|
||||
|
||||
<section class="form-container">
|
||||
<h2>Create an Account</h2>
|
||||
{% if error %}
|
||||
<p class="error">{{ error }}</p>
|
||||
{% endif %}
|
||||
<form action="/register" method="post">
|
||||
<div class="form-group">
|
||||
<label for="full_name">Full Name</label>
|
||||
<input type="text" id="full_name" name="full_name" required value="{{ data.full_name or '' }}">
|
||||
{% if errors.full_name %}
|
||||
<p class="error">{{ errors.full_name }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Work Email Address</label>
|
||||
<input type="email" id="email" name="email" required value="{{ data.email or '' }}">
|
||||
{% if errors.email %}
|
||||
<p class="error">{{ errors.email }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
{% if errors.password %}
|
||||
<p class="error">{{ errors.password }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="confirm_password">Confirm Password</label>
|
||||
<input type="password" id="confirm_password" name="confirm_password" required>
|
||||
{% if errors.confirm_password %}
|
||||
<p class="error">{{ errors.confirm_password }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="terms-checkbox">
|
||||
<input type="checkbox" id="terms" name="terms" required>
|
||||
<label for="terms">I agree to the <a href="/terms">Terms of Service</a> & <a href="/privacy">Privacy Policy</a></label>
|
||||
</div>
|
||||
<button type="submit" class="btn-primary">Create Account</button>
|
||||
</form>
|
||||
<p class="login-link">Already have an account? <a href="/login">Log In</a></p>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
||||
55
retoors/templates/pages/solutions.html
Normal file
@ -0,0 +1,55 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Solutions - Retoor's Cloud Solutions{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/components/solutions.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main>
|
||||
<section class="solutions-hero">
|
||||
<h1>Tailored for Every Business Need</h1>
|
||||
<p>Flexible cloud solutions for teams of all sizes.</p>
|
||||
</section>
|
||||
|
||||
<section class="solutions-grid-section">
|
||||
<div class="solutions-grid">
|
||||
<div class="solution-card">
|
||||
<img src="/static/images/icon-families.svg" alt="Secure File Sharing Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Secure File Sharing</h3>
|
||||
<p>Collaborate on documents and large files with colleagues and clients securely.</p>
|
||||
</div>
|
||||
<div class="solution-card">
|
||||
<img src="/static/images/icon-professionals.svg" alt="Automated Backup Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Automated Backup & Recovery</h3>
|
||||
<p>Protect critical business data with automated, daily easy-click recovery.</p>
|
||||
</div>
|
||||
<div class="solution-card">
|
||||
<img src="/static/images/icon-students.svg" alt="Team Collaboration Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Team Collaboration Spaces</h3>
|
||||
<p>Organize important work documents, collaborate with teams, and access files from anywhere.</p>
|
||||
</div>
|
||||
<div class="solution-card">
|
||||
<img src="/static/images/icon-families.svg" alt="Enterprise Security Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Enterprise-Grade Security</h3>
|
||||
<p>Benefit from advanced encryption and robust access controls.</p>
|
||||
</div>
|
||||
<div class="solution-card">
|
||||
<img src="/static/images/icon-professionals.svg" alt="Compliance Certifications Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Compliance Certifications</h3>
|
||||
<p>Meet industry standards with compliance certifications and robust access controls.</p>
|
||||
</div>
|
||||
<div class="solution-card">
|
||||
<img src="/static/images/icon-students.svg" alt="Scalable Storage Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Scalable Storage Plans</h3>
|
||||
<p>Easily upgrade and downgrade storage as storage and team needs evolve.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="cta-bottom">
|
||||
<a href="/pricing" class="btn-primary">Find Your Business Plan</a>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
75
retoors/templates/pages/support.html
Normal file
@ -0,0 +1,75 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Support - Retoor's Cloud Solutions{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/components/support.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main>
|
||||
<section class="support-hero">
|
||||
<h1>We're Here to Help</h1>
|
||||
<p>Flexible cloud solutions for all teams with ease.</p>
|
||||
</section>
|
||||
|
||||
<section class="support-content-grid">
|
||||
<div class="knowledge-base-section card">
|
||||
<h2>Knowledge Base</h2>
|
||||
<input type="text" class="search-input" placeholder="Search articles and FAQs...">
|
||||
|
||||
<div class="featured-articles">
|
||||
<div class="article-category">
|
||||
<img src="/static/images/icon-families.svg" alt="Getting Started Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Getting Started Guides</h3>
|
||||
<ul>
|
||||
<li><a href="#">How to upload your first files</a></li>
|
||||
<li><a href="#">Setting up your account</a></li>
|
||||
<li><a href="#">Understanding your dashboard</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="article-category">
|
||||
<img src="/static/images/icon-professionals.svg" alt="Troubleshooting Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Troubleshooting Common Issues</h3>
|
||||
<ul>
|
||||
<li><a href="#">Resetting your password</a></li>
|
||||
<li><a href="#">File synchronization problems</a></li>
|
||||
<li><a href="#">Contacting support for technical issues</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="article-category">
|
||||
<img src="/static/images/icon-students.svg" alt="Security Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Security & Privacy FAQs</h3>
|
||||
<ul>
|
||||
<li><a href="#">Understanding data encryption</a></li>
|
||||
<li><a href="#">Our privacy policy explained</a></li>
|
||||
<li><a href="#">Reporting a security vulnerability</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="contact-support-section card">
|
||||
<h2>Contact Support</h2>
|
||||
<div class="contact-option">
|
||||
<img src="/static/images/icon-families.svg" alt="Chat Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Live Chat</h3>
|
||||
<p>Get instant help from our support team.</p>
|
||||
<button class="btn-primary">Chat Now</button>
|
||||
</div>
|
||||
<div class="contact-option">
|
||||
<img src="/static/images/icon-professionals.svg" alt="Email Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Email Support</h3>
|
||||
<p>Submit a detailed request and we'll get back to you.</p>
|
||||
<button class="btn-primary">Submit a Ticket</button>
|
||||
</div>
|
||||
<div class="contact-option">
|
||||
<img src="/static/images/icon-students.svg" alt="Phone Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Phone Support</h3>
|
||||
<p>Speak directly with a support agent.</p>
|
||||
<p class="phone-number">+00 77 5379 033</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
65
retoors/templates/pages/use_cases.html
Normal file
@ -0,0 +1,65 @@
|
||||
{% extends "layouts/base.html" %}
|
||||
|
||||
{% block title %}Use Cases - Retoor's Cloud Solutions{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/static/css/components/use_cases.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main>
|
||||
<section class="use-cases-hero">
|
||||
<h1>Cloud Solutions for Every Industry & Challenge</h1>
|
||||
<p>Flexible cloud storage tailored to your needs.</p>
|
||||
</section>
|
||||
|
||||
<section class="use-cases-grid-section">
|
||||
<div class="use-cases-grid">
|
||||
<div class="use-case-card">
|
||||
<img src="/static/images/icon-families.svg" alt="Secure File Collaboration Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Secure File Collaboration</h3>
|
||||
<p>For marketing and creative teams to share large files and co-edit documents securely.</p>
|
||||
</div>
|
||||
<div class="use-case-card">
|
||||
<img src="/static/images/icon-professionals.svg" alt="Automated Data Backup Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Automated Data Backup</h3>
|
||||
<p>Protect critical business data with automated, daily easy-click recovery.</p>
|
||||
</div>
|
||||
<div class="use-case-card">
|
||||
<img src="/static/images/icon-students.svg" alt="Client & Partner Portals Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Client & Partner Portals</h3>
|
||||
<p>For consulting firms handling sensitive client data, ensure secure access and sharing.</p>
|
||||
</div>
|
||||
<div class="use-case-card">
|
||||
<img src="/static/images/icon-families.svg" alt="Remote Team Access Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Remote Team Access</h3>
|
||||
<p>For businesses with remote workforces needing seamless access to company files from anywhere.</p>
|
||||
</div>
|
||||
<div class="use-case-card">
|
||||
<img src="/static/images/icon-professionals.svg" alt="Centralized Project Storage Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Centralized Project Storage</h3>
|
||||
<p>Streamline project management by centralizing all related documents and assets.</p>
|
||||
</div>
|
||||
<div class="use-case-card">
|
||||
<img src="/static/images/icon-students.svg" alt="Remote Team Archiving Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Remote Team Archiving</h3>
|
||||
<p>Efficiently archive old projects and data, ensuring compliance and easy retrieval.</p>
|
||||
</div>
|
||||
<div class="use-case-card">
|
||||
<img src="/static/images/icon-families.svg" alt="Data Compliance Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Data Compliance & Governance</h3>
|
||||
<p>Meet regulatory requirements with robust data governance and audit trails.</p>
|
||||
</div>
|
||||
<div class="use-case-card">
|
||||
<img src="/static/images/icon-professionals.svg" alt="Disaster Recovery Icon" class="icon"> {# Placeholder icon #}
|
||||
<h3>Disaster Recovery Planning</h3>
|
||||
<p>Ensure business continuity with comprehensive disaster recovery solutions.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="cta-bottom">
|
||||
<a href="/solutions" class="btn-primary">Find Solutions For Your Team</a>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
@ -2,7 +2,7 @@ from aiohttp import web
|
||||
import aiohttp_jinja2
|
||||
from aiohttp_session import get_session, new_session
|
||||
from aiohttp_pydantic import PydanticView
|
||||
from pydantic import BaseModel, EmailStr, Field, ValidationError
|
||||
from pydantic import BaseModel, EmailStr, ValidationError
|
||||
|
||||
from ..services.user_service import UserService
|
||||
from ..models import RegistrationModel
|
||||
@ -32,7 +32,7 @@ class LoginView(CustomPydanticView):
|
||||
|
||||
async def get(self):
|
||||
return aiohttp_jinja2.render_template(
|
||||
self.template_name, self.request, {"request": self.request, "errors": {}}
|
||||
self.template_name, self.request, {"request": self.request, "errors": {}, "data": {}}
|
||||
)
|
||||
|
||||
async def post(self):
|
||||
@ -41,7 +41,7 @@ class LoginView(CustomPydanticView):
|
||||
except ValidationError as e:
|
||||
errors = {err["loc"][0]: err["msg"] for err in e.errors()}
|
||||
return aiohttp_jinja2.render_template(
|
||||
self.template_name, self.request, {"errors": errors, "request": self.request}
|
||||
self.template_name, self.request, {"errors": errors, "request": self.request, "data": dict(await self.request.post())}
|
||||
)
|
||||
|
||||
user_service: UserService = self.request.app["user_service"]
|
||||
@ -53,7 +53,7 @@ class LoginView(CustomPydanticView):
|
||||
return aiohttp_jinja2.render_template(
|
||||
self.template_name,
|
||||
self.request,
|
||||
{"error": "Invalid email or password", "request": self.request, "errors": {}},
|
||||
{"error": "Invalid email or password", "request": self.request, "errors": {}, "data": dict(await self.request.post())},
|
||||
)
|
||||
|
||||
|
||||
@ -62,29 +62,29 @@ class RegistrationView(CustomPydanticView):
|
||||
|
||||
async def get(self):
|
||||
return aiohttp_jinja2.render_template(
|
||||
self.template_name, self.request, {"request": self.request, "errors": {}}
|
||||
self.template_name, self.request, {"request": self.request, "errors": {}, "data": {}}
|
||||
)
|
||||
|
||||
async def post(self):
|
||||
data = await self.request.post() # Get raw form data once
|
||||
try:
|
||||
user_data = RegistrationModel(**await self.request.post())
|
||||
user_data = RegistrationModel(**data)
|
||||
except ValidationError as e:
|
||||
errors = {err["loc"][0]: err["msg"] for err in e.errors()}
|
||||
return aiohttp_jinja2.render_template(
|
||||
self.template_name, self.request, {"errors": errors, "request": self.request}
|
||||
self.template_name, self.request, {"errors": errors, "request": self.request, "data": dict(data)}
|
||||
)
|
||||
|
||||
data = await self.request.post()
|
||||
if user_data.password != data.get("confirm_password"):
|
||||
return aiohttp_jinja2.render_template(
|
||||
self.template_name,
|
||||
self.request,
|
||||
{"error": "Passwords do not match", "request": self.request, "errors": {}},
|
||||
{"error": "Passwords do not match", "request": self.request, "errors": {}, "data": dict(data)},
|
||||
)
|
||||
|
||||
user_service: UserService = self.request.app["user_service"]
|
||||
try:
|
||||
user_service.create_user(user_data.username, user_data.email, user_data.password)
|
||||
user_service.create_user(user_data.full_name, user_data.email, user_data.password) # Changed username to full_name
|
||||
except ValueError:
|
||||
return aiohttp_jinja2.render_template(
|
||||
self.template_name,
|
||||
@ -93,6 +93,7 @@ class RegistrationView(CustomPydanticView):
|
||||
"error": "User with this email already exists",
|
||||
"request": self.request,
|
||||
"errors": {},
|
||||
"data": dict(data),
|
||||
},
|
||||
)
|
||||
|
||||
@ -13,8 +13,10 @@ class SiteView(web.View):
|
||||
async def get(self):
|
||||
if self.request.path == "/dashboard":
|
||||
return await self.dashboard()
|
||||
elif self.request.path == "/solutions":
|
||||
return await self.solutions()
|
||||
return aiohttp_jinja2.render_template(
|
||||
"pages/home.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
||||
"pages/index.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
||||
)
|
||||
|
||||
@login_required
|
||||
@ -25,9 +27,30 @@ class SiteView(web.View):
|
||||
{"user": self.request["user"], "request": self.request, "errors": {}},
|
||||
)
|
||||
|
||||
async def solutions(self):
|
||||
return aiohttp_jinja2.render_template(
|
||||
"pages/solutions.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
||||
)
|
||||
|
||||
async def support(self):
|
||||
return aiohttp_jinja2.render_template(
|
||||
"pages/support.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
||||
)
|
||||
|
||||
async def use_cases(self):
|
||||
return aiohttp_jinja2.render_template(
|
||||
"pages/use_cases.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
||||
)
|
||||
|
||||
|
||||
class OrderView(CustomPydanticView):
|
||||
template_name = "pages/dashboard.html"
|
||||
template_name = "pages/order.html"
|
||||
|
||||
@login_required
|
||||
async def get(self):
|
||||
return aiohttp_jinja2.render_template(
|
||||
self.template_name, self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
||||
)
|
||||
|
||||
@login_required
|
||||
async def post(self):
|
||||
@ -1,11 +1,10 @@
|
||||
import pytest
|
||||
from aiohttp import web
|
||||
|
||||
|
||||
async def test_login_get(client):
|
||||
resp = await client.get("/login")
|
||||
assert resp.status == 200
|
||||
text = await resp.text()
|
||||
assert "Access Your Retoor's Cloud Account" in text
|
||||
assert "Login to your Account" in text
|
||||
|
||||
|
||||
@ -13,6 +12,7 @@ async def test_register_get(client):
|
||||
resp = await client.get("/register")
|
||||
assert resp.status == 200
|
||||
text = await resp.text()
|
||||
assert "Create Your Retoor's Cloud Account" in text
|
||||
assert "Create an Account" in text
|
||||
assert resp.url.path == "/register"
|
||||
|
||||
@ -21,7 +21,7 @@ async def test_register_post_password_mismatch(client):
|
||||
resp = await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser",
|
||||
"full_name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"password": "password",
|
||||
"confirm_password": "wrong_password",
|
||||
@ -36,7 +36,7 @@ async def test_register_post_user_exists(client):
|
||||
await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser",
|
||||
"full_name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"password": "password",
|
||||
"confirm_password": "password",
|
||||
@ -45,7 +45,7 @@ async def test_register_post_user_exists(client):
|
||||
resp = await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser2",
|
||||
"full_name": "Test User 2",
|
||||
"email": "test@example.com",
|
||||
"password": "password",
|
||||
"confirm_password": "password",
|
||||
@ -60,7 +60,7 @@ async def test_register_post_invalid_email(client):
|
||||
resp = await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser",
|
||||
"full_name": "Test User",
|
||||
"email": "invalid-email",
|
||||
"password": "password",
|
||||
"confirm_password": "password",
|
||||
@ -75,7 +75,7 @@ async def test_register_post_short_password(client):
|
||||
resp = await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser",
|
||||
"full_name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"password": "short",
|
||||
"confirm_password": "short",
|
||||
@ -90,7 +90,7 @@ async def test_login_post(client):
|
||||
await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser",
|
||||
"full_name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"password": "password",
|
||||
"confirm_password": "password",
|
||||
@ -116,7 +116,7 @@ async def test_logout(client):
|
||||
await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser",
|
||||
"full_name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"password": "password",
|
||||
"confirm_password": "password",
|
||||
@ -1,12 +1,12 @@
|
||||
import pytest
|
||||
from aiohttp import web
|
||||
|
||||
|
||||
async def test_index_get(client):
|
||||
resp = await client.get("/")
|
||||
assert resp.status == 200
|
||||
text = await resp.text()
|
||||
assert "Retoor's Search" in text
|
||||
assert "Elevate Your Business Data" in text
|
||||
assert "Start Free Trial" in text
|
||||
|
||||
|
||||
async def test_dashboard_get_unauthorized(client):
|
||||
resp = await client.get("/dashboard", allow_redirects=False)
|
||||
@ -18,7 +18,7 @@ async def test_dashboard_get_authorized(client):
|
||||
await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser",
|
||||
"full_name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"password": "password",
|
||||
"confirm_password": "password",
|
||||
@ -30,7 +30,8 @@ async def test_dashboard_get_authorized(client):
|
||||
resp = await client.get("/dashboard")
|
||||
assert resp.status == 200
|
||||
text = await resp.text()
|
||||
assert "Welcome, test@example.com" in text
|
||||
assert "Your Data, Organized and Accessible" in text
|
||||
assert "My Files" in text
|
||||
|
||||
|
||||
async def test_order_post_unauthorized(client):
|
||||
@ -45,7 +46,7 @@ async def test_order_post_authorized(client):
|
||||
await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser",
|
||||
"full_name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"password": "password",
|
||||
"confirm_password": "password",
|
||||
@ -68,7 +69,7 @@ async def test_order_post_invalid_amount(client):
|
||||
await client.post(
|
||||
"/register",
|
||||
data={
|
||||
"username": "testuser",
|
||||
"full_name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"password": "password",
|
||||
"confirm_password": "password",
|
||||