Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,5 @@ cython_debug/
.idea/
.DS_Store
**/.DS_Store/**
**/migrations/**
**/migrations/**
/services/
51 changes: 34 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Django Appointment 📦

⚠️ **IMPORTANT**: Version 2.0.0 introduces significant database changes. Please read the [migration guide](https://github.com/adamspd/django-appointment/tree/main/migration_guide_v2.0.0.md) before updating.
⚠️ **IMPORTANT**: Version 2.1.0 introduces significant database changes. Please read
the [migration guide](https://github.com/adamspd/django-appointment/tree/main/migration_guide_v2.1.0.md) before
updating.

Django-Appointment is a Django app engineered for managing appointment scheduling with ease and flexibility. It enables
users to define custom configurations for time slots, lead time, and finish time, or utilize the default values
Expand All @@ -20,8 +22,12 @@ notes [here](https://github.com/adamspd/django-appointment/tree/main/release_not
4. User-friendly interface for viewing available time slots and scheduling appointments.
5. Capability to send email notifications to clients upon scheduling an appointment.

## Added Features in version 2.0.0 🆕
- **Database Changes ⚠️**: Significant modifications to the database schema. Before updating, ensure you follow the migration steps outlined in the [migration guide](https://github.com/adamspd/django-appointment/tree/main/migration_guide_v2.0.0.md).
## Added Features in version 2.0.0

- **Database Changes ⚠️**: Significant modifications to the database schema. Before updating, ensure you follow the
migration steps outlined in
the [migration guide](https://github.com/adamspd/django-appointment/tree/main/migration_guide_v2.1.0.md).

1. Introduced a staff feature allowing staff members in a team or system to manage their own appointments.
2. Implemented an admin feature panel enabling staff members and superusers (admins) to manage the system.
3. Added buffer time between the current time and the first available slot for the day.
Expand All @@ -30,6 +36,15 @@ notes [here](https://github.com/adamspd/django-appointment/tree/main/release_not
6. Staff members can now define their own configuration settings for the appointment system, such as slot duration,
working hours, and buffer time between appointments. However, only admins have the privilege to add/remove services.

### Breaking Changes in version 2.1.0:
- None

### New Features 🆕
See the [release notes](release_notes.md#Updates) for more information.

### Fixes 🆕
See the [release notes](release_notes.md#Bug-Fixes) for more information.

## Quick Start 🚀

1. Add "appointment" to your `INSTALLED_APPS` setting like so:
Expand Down Expand Up @@ -57,40 +72,42 @@ notes [here](https://github.com/adamspd/django-appointment/tree/main/release_not
```python
AUTH_USER_MODEL = 'models.UserModel' # Optional if you use Django's user model
```

For instance, if you employ a custom user model:

```python
AUTH_USER_MODEL = 'client.UserClient'
```

If you're utilizing the default Django user model, there's no need to add this line since Django automatically sets it

If you're utilizing the default Django user model, there's no need to add this line since Django automatically sets
it
to:

```python
AUTH_USER_MODEL = 'auth.User'
```

Ensure your `create_user` function includes the following arguments, even if they are not all utilized:

```python
def create_user(first_name, email, username, last_name=None, **extra_fields):
pass
```

This function will create a user with a password formatted as: f"{APPOINTMENT_WEBSITE_NAME}{current_year}"

For instance, if you append this to your `settings.py`:

```python
APPOINTMENT_WEBSITE_NAME = 'Chocolates'
```

And the current year is 2023, the password will be "Chocolates2023". If `APPOINTMENT_WEBSITE_NAME` is not provided, the

And the current year is 2023, the password will be "Chocolates2023". If `APPOINTMENT_WEBSITE_NAME` is not provided,
the
default value is "Website", rendering the password as "Website2023".

This name is also utilized in the footer of the emails sent to clients upon scheduling an appointment:

```html
<p>® 2023 {{ APPOINTMENT_WEBSITE_NAME }}. All Rights Reserved.</p>
```
Expand Down
1 change: 0 additions & 1 deletion appointment/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

"""
Author: Adams Pierre David
Version: 2.0.0
Since: 1.0.0
"""

Expand Down
1 change: 0 additions & 1 deletion appointment/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

"""
Author: Adams Pierre David
Version: 2.0.0
Since: 1.0.0
"""

Expand Down
1 change: 0 additions & 1 deletion appointment/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

"""
Author: Adams Pierre David
Version: 2.0.0
Since: 2.0.0
"""

Expand Down
1 change: 0 additions & 1 deletion appointment/email_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

"""
Author: Adams Pierre David
Version: 2.0.0
Since: 1.1.0
"""

Expand Down
33 changes: 26 additions & 7 deletions appointment/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

"""
Author: Adams Pierre David
Version: 2.0.0
Since: 1.0.0
"""

Expand Down Expand Up @@ -127,17 +126,37 @@ class Meta:


class ServiceForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ServiceForm, self).__init__(*args, **kwargs)
if self.instance and self.instance.pk:
self.fields['background_color'].widget.attrs['value'] = self.instance.background_color

class Meta:
model = Service
fields = ['name', 'description', 'duration', 'price', 'down_payment', 'image', 'currency', 'background_color']
widgets = {
'name': forms.TextInput(attrs={'class': 'form-control'}),
'description': forms.Textarea(attrs={'class': 'form-control'}),
'duration': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'HH:MM:SS'}),
'price': forms.NumberInput(attrs={'class': 'form-control'}),
'down_payment': forms.NumberInput(attrs={'class': 'form-control'}),
'name': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': _('Example: First Consultation')
}),
'description': forms.Textarea(attrs={
'class': 'form-control',
'placeholder': "Example: Overview of client's needs."
}),
'duration': forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'HH:MM:SS, (example: 00:15:00 for 15 minutes)'
}),
'price': forms.NumberInput(attrs={
'class': 'form-control',
'placeholder': 'Example: 100.00 (0 for free)'
}),
'down_payment': forms.NumberInput(attrs={
'class': 'form-control',
'placeholder': 'Example: 50.00 (0 for free)'
}),
'image': forms.ClearableFileInput(attrs={'class': 'form-control'}),
'currency': forms.Select(choices=[('USD', 'USD'), ('EUR', 'EUR'), ('GBP', 'GBP')],
attrs={'class': 'form-control'}),
'background_color': forms.TextInput(attrs={'class': 'form-control', 'type': 'color'}),
'background_color': forms.TextInput(attrs={'class': 'form-control', 'type': 'color', 'value': '#000000'}),
}
1 change: 0 additions & 1 deletion appointment/logger_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

"""
Author: Adams Pierre David
Version: 2.0.0
Since: 1.1.0
"""

Expand Down
4 changes: 2 additions & 2 deletions appointment/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

"""
Author: Adams Pierre David
Version: 2.0.0
Since: 1.0.0
"""
import colorsys
Expand Down Expand Up @@ -152,6 +151,8 @@ def get_down_payment_str(self):
return f"{self.get_down_payment()}{self.get_currency_icon()}"

def get_image_url(self):
if not self.image:
return ""
return self.image.url

def is_a_paid_service(self):
Expand Down Expand Up @@ -277,7 +278,6 @@ class AppointmentRequest(models.Model):
Represents an appointment request made by a client.

Author: Adams Pierre David
Version: 2.0.0
Since: 1.0.0
"""
date = models.DateField()
Expand Down
7 changes: 3 additions & 4 deletions appointment/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

"""
Author: Adams Pierre David
Version: 2.0.0
Since: 2.0.0
"""

Expand Down Expand Up @@ -520,13 +519,13 @@ def create_staff_member_service(post_data):
return None, False, get_error_message_in_form(form=form)


def handle_service_management_request(post_data, service_id=None):
def handle_service_management_request(post_data, files_data=None, service_id=None):
try:
if service_id:
service = Service.objects.get(pk=service_id)
form = ServiceForm(post_data, instance=service)
form = ServiceForm(post_data, files_data, instance=service)
else:
form = ServiceForm(post_data)
form = ServiceForm(post_data, files_data)

if form.is_valid():
form.save()
Expand Down
1 change: 0 additions & 1 deletion appointment/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

"""
Author: Adams Pierre David
Version: 2.0.0
Since: 1.0.0
"""

Expand Down
4 changes: 2 additions & 2 deletions appointment/static/css/app_admin/user_profile.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ body {
}

.profile-container {
margin: 0 auto;
margin: 5px auto;
background-color: #fff;
border-radius: 8px;
}
Expand Down Expand Up @@ -182,7 +182,7 @@ table tbody tr:hover {

/* Adding gradient backgrounds for a more vibrant look */
.profile-container {
background-image: linear-gradient(to bottom right, #fff, #f7f9fc);
/*background-image: linear-gradient(to bottom right, #fff, #f7f9fc);*/
}

/* Additional hover effect for the sections */
Expand Down
84 changes: 83 additions & 1 deletion appointment/static/css/appointments.css
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,89 @@ a {
}
}

/* CSS for screens smaller or equal to 768px */
@media (max-width: 450px) {
.djangoAppt_main-container {
padding: 3px;
}

.djangoAppt_body-container {
padding: 3px;
}

.djangoAppt_appointment-calendar {
flex: 1;
padding: 5px;
}

.djangoAppt_service-description {
flex: 1;
margin-left: 0;
margin-top: 20px;
}

.djangoAppt_calendar-and-slot {
display: grid;
}

.djangoAppt_slot {
margin-top: 40px;
}

.djangoAppt_slot-list, .djangoAppt_date_chosen, .djangoAppt_no-availability-text {
margin-left: 0 !important;
padding-left: 0 !important;
}

.djangoAppt_btn-request-next-slot {
margin-left: 0;
}

/* Reduce font size for smaller screens */
.djangoAppt_title, .djangoAppt_item-name, .djangoAppt_date_chosen, .djangoAppt_next-available-date {
font-size: 13px;
}

.djangoAppt_timezone-details, .error-message {
font-size: 13px;
}

.fc-day {
font-size: 11px;
}

.fc-toolbar-title {
font-size: 14px !important;
}

.fc {
font-size: 13px !important;
}

.fc, .fc-button {
padding: .3em .45em !important;
vertical-align: center !important;
}

.fc-daygrid-day-events {
display: none !important;
margin: 0 !important;
padding: 0 !important;
font-size: 0 !important;
height: 0 !important;
}

.djangoAppt_appointment-slot {
padding: 5px;
font-size: 13px;
}

.djangoAppt_service-description {
font-size: 13px !important;
}
}

.selected-cell {
background-color: #aaddff; /* or any color you prefer */
background-color: #aaddff; /* or any color you prefer */
}

Loading