Skip to content
48 changes: 48 additions & 0 deletions backend/samfundet/migrations/0006_venue_is_open_days.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Generated manually for is_open_* fields

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('samfundet', '0005_medlemsinfo'),
]

operations = [
migrations.AddField(
model_name='venue',
name='is_open_monday',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='venue',
name='is_open_tuesday',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='venue',
name='is_open_wednesday',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='venue',
name='is_open_thursday',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='venue',
name='is_open_friday',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='venue',
name='is_open_saturday',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='venue',
name='is_open_sunday',
field=models.BooleanField(default=True),
),
]
9 changes: 9 additions & 0 deletions backend/samfundet/models/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,15 @@ class Venue(CustomBaseModel):
closing_saturday = models.TimeField(default=time(hour=20), blank=True, null=True)
closing_sunday = models.TimeField(default=time(hour=20), blank=True, null=True)

# Is the venue open on this day?
is_open_monday = models.BooleanField(default=True)
is_open_tuesday = models.BooleanField(default=True)
is_open_wednesday = models.BooleanField(default=True)
is_open_thursday = models.BooleanField(default=True)
is_open_friday = models.BooleanField(default=True)
is_open_saturday = models.BooleanField(default=True)
is_open_sunday = models.BooleanField(default=True)

class Meta:
verbose_name = 'Venue'
verbose_name_plural = 'Venues'
Expand Down
7 changes: 5 additions & 2 deletions backend/samfundet/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,25 +282,28 @@ def test_open_venues_filtering(
'slug': open_slug,
f'opening_{day_of_week}': open_time,
f'closing_{day_of_week}': close_time,
f'is_open_{day_of_week}': True,
}
self._create_venue(**open_venue_kwargs)

# 2. Venue that is explicitly closed (00:00 - 00:00)
# 2. Venue that is explicitly closed (is_open_* = False)
closed_venue_kwargs = {
'slug': closed_slug,
f'opening_{day_of_week}': zero_time,
f'closing_{day_of_week}': zero_time,
f'is_open_{day_of_week}': False,
}
self._create_venue(**closed_venue_kwargs)

# 3. Venue open on a different day (should be treated as closed on the test day if explicitly set to 0:00-0:00)
# 3. Venue open on a different day (should be treated as closed on the test day)
other_slug = 'other_day'
other_day_kwargs = {
'slug': other_slug,
'opening_tuesday': open_time,
'closing_tuesday': close_time,
f'opening_{day_of_week}': zero_time,
f'closing_{day_of_week}': zero_time,
f'is_open_{day_of_week}': False,
}
self._create_venue(**other_day_kwargs)

Expand Down
14 changes: 4 additions & 10 deletions backend/samfundet/view/general_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from __future__ import annotations

from typing import Any
from datetime import time, timedelta
from datetime import timedelta
from itertools import chain

from rest_framework import status
Expand All @@ -18,7 +18,7 @@
from rest_framework.permissions import AllowAny

from django.utils import timezone
from django.db.models import Q, QuerySet
from django.db.models import QuerySet
from django.shortcuts import get_object_or_404

from root.constants import WebFeatures
Expand Down Expand Up @@ -134,16 +134,10 @@ class VenueView(ModelViewSet):

@action(detail=False, methods=['get'])
def open_venues(self, request: Request) -> Response:
# Note: This 4-hour offset must match frontend getVenueDay() in utils.ts
day_name = (timezone.now() - timedelta(hours=4)).strftime('%A').lower()

q = ~Q(
**{
f'opening_{day_name}': time(0, 0, 0),
f'closing_{day_name}': time(0, 0, 0),
}
)

open_venues = Venue.objects.filter(q)
open_venues = Venue.objects.filter(**{f'is_open_{day_name}': True})
serializer = self.get_serializer(open_venues, many=True)
return Response(serializer.data)

Expand Down
7 changes: 6 additions & 1 deletion frontend/src/Components/Checkbox/Checkbox.module.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* stylelint-disable selector-max-compound-selectors */
@use 'src/constants' as *;

@use 'src/mixins' as *;
$checkmark: '\2714'; /* ASCII "check"-symbol. */

/* Label wraper i checkbox.tsx. */
Expand Down Expand Up @@ -31,7 +33,10 @@ $checkmark: '\2714'; /* ASCII "check"-symbol. */
margin-right: 10px;
margin-left: 10px;
flex-shrink: 0;
transition: background 0.15s, border-color 0.15s; /* Bakgrunn kommer gradvis inn. */

@include theme-dark {
border-color: $grey-0;
}
}

/* Her velges (og styles) det elementet med klassen .checkbox__box som ligger rett etter(ved bruk av +) elementet med klassen .checkbox__input, når det sistnevnte elementet er "checked". */
Expand Down
33 changes: 30 additions & 3 deletions frontend/src/Components/InputTime/InputTime.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

@use 'src/mixins' as *;

.inputTime_wrap {
border-radius: 0.375rem;
border: 1px solid $grey-35;
box-shadow: 0 1px 2px 0 $black-t10;

@include theme-dark {
border-color: $grey-2;
}
}

.inputTime_wrap:focus-within {
border-color: $grey-1;
box-shadow: 0 0 0 1px $grey-1;
outline: none;

@include theme-dark {
border-color: $grey-35;
box-shadow: 0 0 0 1px $grey-35;
}
}

.inputTime {
display: flex;
align-items: left;
Expand All @@ -13,9 +34,11 @@
box-sizing: border-box;
padding: auto 5px;
text-align: center;
border: 2px solid $grey-4;
border: none;
background-color: transparent;

@include theme-dark {
border-color: $grey-2;
color: $white;
}
}

Expand All @@ -38,7 +61,11 @@

.number:focus {
outline: 3px hidden var(--active);
box-shadow: 0 0 2px 2px #999999;
}

.number:disabled {
opacity: 0.7;
cursor: not-allowed;
}

.error {
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/Components/InputTime/InputTime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type InputTimeProps = {
error?: string;
};

export function InputTime({ onChange, onBlur, value, error }: InputTimeProps) {
export function InputTime({ className, disabled, onChange, onBlur, value, error }: InputTimeProps) {
const [hour, setHour] = useState('');
const [minute, setMinute] = useState('');

Expand Down Expand Up @@ -56,13 +56,14 @@ export function InputTime({ onChange, onBlur, value, error }: InputTimeProps) {
}

return (
<div className={styles.inputTime_wrap}>
<div className={classNames(styles.inputTime_wrap, className)}>
<div className={classNames(styles.inputTime, error && styles.error)}>
<input
type="text"
className={classNames(styles.number, error && styles.error)}
name="hour"
value={hour}
disabled={disabled}
onChange={handleChange}
onBlur={handleBlur}
/>
Expand All @@ -72,6 +73,7 @@ export function InputTime({ onChange, onBlur, value, error }: InputTimeProps) {
className={classNames(styles.number, error && styles.error)}
name="minute"
value={minute}
disabled={disabled}
onChange={handleChange}
onBlur={handleBlur}
/>
Expand Down
107 changes: 58 additions & 49 deletions frontend/src/Components/OpeningHours/OpeningHours.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const meta: Meta<typeof OpeningHours> = {

export default meta;

type Story = StoryObj<typeof OpeningHours>;
type Story = StoryObj<typeof meta>;

export const Basic: Story = {
args: {
Expand All @@ -20,75 +20,84 @@ export const Basic: Story = {
name: 'Daglighallen',
opening_monday: '08:00:00',
closing_monday: '20:00:00',
is_open_monday: true,
opening_tuesday: '08:00:00',
closing_tuesday: '20:00:00',
is_open_tuesday: true,
opening_wednesday: '08:00:00',
closing_wednesday: '20:00:00',
is_open_wednesday: true,
opening_thursday: '08:00:00',
closing_thursday: '20:00:00',
is_open_thursday: true,
opening_friday: '08:00:00',
closing_friday: '20:00:00',
is_open_friday: true,
opening_saturday: '08:00:00',
closing_saturday: '20:00:00',
is_open_saturday: true,
opening_sunday: '08:00:00',
closing_sunday: '20:00:00',
is_open_sunday: true,
},
{
id: 2,
slug: 'edgar',
name: 'Edgar',
opening_monday: '08:00:00',
closing_monday: '20:00:00',
opening_tuesday: '08:00:00',
closing_tuesday: '20:00:00',
opening_wednesday: '08:00:00',
closing_wednesday: '20:00:00',
opening_thursday: '08:00:00',
closing_thursday: '20:00:00',
opening_friday: '08:00:00',
closing_friday: '20:00:00',
opening_saturday: '08:00:00',
closing_saturday: '20:00:00',
opening_sunday: '08:00:00',
closing_sunday: '20:00:00',
opening_monday: '10:00:00',
closing_monday: '22:00:00',
is_open_monday: true,
opening_tuesday: '10:00:00',
closing_tuesday: '22:00:00',
is_open_tuesday: true,
opening_wednesday: '10:00:00',
closing_wednesday: '22:00:00',
is_open_wednesday: true,
opening_thursday: '10:00:00',
closing_thursday: '22:00:00',
is_open_thursday: true,
opening_friday: '10:00:00',
closing_friday: '23:00:00',
is_open_friday: true,
opening_saturday: '10:00:00',
closing_saturday: '23:00:00',
is_open_saturday: true,
opening_sunday: '00:00:00',
closing_sunday: '00:00:00',
is_open_sunday: false,
},
],
},
};

export const WithClosedDays: Story = {
args: {
venues: [
{
id: 3,
id: 1,
slug: 'klubben',
name: 'Klubben',
opening_monday: '08:00:00',
closing_monday: '20:00:00',
opening_tuesday: '08:00:00',
closing_tuesday: '20:00:00',
opening_wednesday: '08:00:00',
closing_wednesday: '20:00:00',
opening_thursday: '08:00:00',
closing_thursday: '20:00:00',
opening_friday: '08:00:00',
closing_friday: '20:00:00',
opening_saturday: '08:00:00',
closing_saturday: '20:00:00',
opening_sunday: '08:00:00',
closing_sunday: '20:00:00',
},
{
id: 4,
slug: 'storsalen',
name: 'Storsalen',
opening_monday: '08:00:00',
closing_monday: '20:00:00',
opening_tuesday: '08:00:00',
closing_tuesday: '20:00:00',
opening_wednesday: '08:00:00',
closing_wednesday: '20:00:00',
opening_thursday: '08:00:00',
closing_thursday: '20:00:00',
opening_friday: '08:00:00',
closing_friday: '20:00:00',
opening_saturday: '08:00:00',
closing_saturday: '20:00:00',
opening_sunday: '08:00:00',
closing_sunday: '20:00:00',
opening_monday: '00:00:00',
closing_monday: '00:00:00',
is_open_monday: false,
opening_tuesday: '00:00:00',
closing_tuesday: '00:00:00',
is_open_tuesday: false,
opening_wednesday: '18:00:00',
closing_wednesday: '02:00:00',
is_open_wednesday: true,
opening_thursday: '18:00:00',
closing_thursday: '02:00:00',
is_open_thursday: true,
opening_friday: '18:00:00',
closing_friday: '03:00:00',
is_open_friday: true,
opening_saturday: '18:00:00',
closing_saturday: '03:00:00',
is_open_saturday: true,
opening_sunday: '00:00:00',
closing_sunday: '00:00:00',
is_open_sunday: false,
},
],
},
Expand Down
Loading
Loading