Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
575a499
Add darkmode to storybook
eilifhl Sep 23, 2025
fa443e5
Remove bg color
eilifhl Sep 23, 2025
f14c2a2
Revise Venue Opening Dto
eilifhl Sep 23, 2025
a1d65d0
Change route naming
eilifhl Sep 25, 2025
9d3231f
Change request from patch to get
eilifhl Sep 25, 2025
cb63071
Create open_venues function in VenueView
eilifhl Sep 25, 2025
532c81b
Generate routes
eilifhl Sep 25, 2025
1bd43d8
Remove irrelevant routes changes
eilifhl Sep 30, 2025
9d3188e
Merge branch 'master' into Eilif/1942-get-opening-hours-for-homepage-…
eilifhl Sep 30, 2025
9781938
Refactor api call to deliver venue list instead of new datatype
eilifhl Sep 30, 2025
697e60e
Merge branch 'master' into Eilif/1942-get-opening-hours-for-homepage-…
eilifhl Sep 30, 2025
567abe2
Create container component
eilifhl Sep 30, 2025
c8e02d5
Merge branch 'Eilif/1942-get-opening-hours-for-homepage-backend' of g…
eilifhl Sep 30, 2025
e01573d
Refactor so all logic is in OpeningHours.tsx
eilifhl Sep 30, 2025
fcb4de4
Remove OpeningHoursContainer from HomePage
eilifhl Oct 2, 2025
dc90eb2
BIOMEEEEEE
eilifhl Oct 2, 2025
2880626
STYLELIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIINTTTTTT
eilifhl Oct 2, 2025
4df319a
Add correct storybook data
eilifhl Oct 2, 2025
388bed0
Fix styling of tableCell border
eilifhl Oct 7, 2025
330f699
Venues with midnight opening, closing are closed
eilifhl Oct 7, 2025
175b534
Merge branch 'master' into Eilif/1942-get-opening-hours-for-homepage-…
eilifhl Oct 16, 2025
2611eba
Make tests for open_venues
eilifhl Oct 23, 2025
36462f0
Merge branch 'master' into Eilif/1942-get-opening-hours-for-homepage-…
eilifhl Oct 23, 2025
8e7b3b8
Fix datetime import
eilifhl Oct 23, 2025
7330149
ci: add freezegun to dev dependencies
eilifhl Oct 23, 2025
226d5c0
Use queryKey best practice in OpeningHoursContainer.tsx
eilifhl Nov 4, 2025
2cc4ae5
BIOOOOOOOOOOOOOOOOOOOOOOOOOOOMEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE…
eilifhl Nov 4, 2025
83aeae9
Lol fix compiler errors
eilifhl Nov 4, 2025
f89b0a9
Merge branch 'master' into Eilif/1942-get-opening-hours-for-homepage-…
eilifhl Nov 4, 2025
b898033
Merge branch 'master' into Eilif/1942-get-opening-hours-for-homepage-…
eilifhl Nov 6, 2025
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
44 changes: 43 additions & 1 deletion backend/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ requests = "2.*"
pytest = "8.*"
pytest-django = "4.*"
drf-spectacular = "0.28.*"
freezegun = "^1.5.5"

[build-system]
requires = ["poetry-core"]
Expand Down
1 change: 1 addition & 0 deletions backend/root/utils/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@
samfundet__eventgroups_list = 'samfundet:eventgroups-list'
samfundet__eventgroups_detail = 'samfundet:eventgroups-detail'
samfundet__venues_list = 'samfundet:venues-list'
samfundet__venues_open_venues = 'samfundet:venues-open-venues'
samfundet__venues_detail = 'samfundet:venues-detail'
samfundet__closedperiods_list = 'samfundet:closedperiods-list'
samfundet__closedperiods_detail = 'samfundet:closedperiods-detail'
Expand Down
141 changes: 140 additions & 1 deletion backend/samfundet/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from __future__ import annotations

import time
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any
from datetime import date
from datetime import time as dt_time

import pytest
import freezegun
from guardian.shortcuts import assign_perm

from rest_framework import status
Expand Down Expand Up @@ -217,6 +219,143 @@ def test_user_alreadyexists(self, fixture_rest_client: APIClient):
assert RegisterSerializer.ALREADY_EXISTS_MESSAGE in data[field]


@pytest.mark.django_db
class TestVenueOpenViews:
# Assuming the route is named like this based on other tests
url = reverse(routes.samfundet__venues_open_venues)

def _create_venue(self, slug: str, **kwargs: Any) -> Venue:
"""Helper to create a Venue object with minimal required fields and default opening hours."""
zero_time = dt_time(0, 0, 0)
default_data = {
'name': f'Venue {slug}',
'slug': slug,
# Set all opening/closing to default (8:00/20:00) or 00:00/00:00 if closed
'opening_monday': dt_time(8, 0),
'closing_monday': dt_time(20, 0),
'opening_tuesday': dt_time(8, 0),
'closing_tuesday': dt_time(20, 0),
'opening_wednesday': dt_time(8, 0),
'closing_wednesday': dt_time(20, 0),
'opening_thursday': dt_time(8, 0),
'closing_thursday': dt_time(20, 0),
'opening_friday': dt_time(8, 0),
'closing_friday': dt_time(20, 0),
'opening_saturday': dt_time(8, 0),
'closing_saturday': dt_time(20, 0),
'opening_sunday': zero_time,
'closing_sunday': zero_time, # closed on Sunday
}
default_data.update(kwargs)
return Venue.objects.create(**default_data)

@pytest.mark.parametrize(
'day_of_week, open_slug, closed_slug, test_date',
[
# Monday (0)
('monday', 'open_mon', 'closed_mon', '2023-10-23 12:00:00'),
# Thursday (3)
('thursday', 'open_thu', 'closed_thu', '2023-10-26 12:00:00'),
# Sunday (6)
('sunday', 'open_sun', 'closed_sun', '2023-10-29 12:00:00'),
],
)
def test_open_venues_filtering(
self,
fixture_rest_client: APIClient,
day_of_week: str,
open_slug: str,
closed_slug: str,
test_date: str,
):
"""
Test that only venues with non-00:00-00:00 opening/closing hours for the
current day are returned.
"""
zero_time = dt_time(0, 0, 0)
open_time = dt_time(10, 0, 0)
close_time = dt_time(18, 0, 0)

# 1. Venue that is explicitly open
open_venue_kwargs = {
'slug': open_slug,
f'opening_{day_of_week}': open_time,
f'closing_{day_of_week}': close_time,
}
self._create_venue(**open_venue_kwargs)

# 2. Venue that is explicitly closed (00:00 - 00:00)
closed_venue_kwargs = {
'slug': closed_slug,
f'opening_{day_of_week}': zero_time,
f'closing_{day_of_week}': zero_time,
}
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)
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,
}
self._create_venue(**other_day_kwargs)

# Use freezegun to set the current day and time
with freezegun.freeze_time(test_date):
# Act
response: Response = fixture_rest_client.get(path=self.url)

# Assert
assert status.is_success(code=response.status_code)
data = response.json()

# We expect only the venue with non-zero opening hours to be included
assert len(data) == 1
assert data[0]['slug'] == open_slug
# Check the returned times for the open venue
assert data[0][f'opening_{day_of_week}'] == open_time.strftime('%H:%M:%S')
assert data[0][f'closing_{day_of_week}'] == close_time.strftime('%H:%M:%S')

def test_open_venues_no_venues(self, fixture_rest_client: APIClient):
"""Test with no venues in the database."""
with freezegun.freeze_time('2023-10-23 12:00:00'): # Monday
# Act
response: Response = fixture_rest_client.get(path=self.url)

# Assert
assert status.is_success(code=response.status_code)
assert len(response.data) == 0

def test_open_venues_not_excluded_when_one_time_is_non_zero(self, fixture_rest_client: APIClient):
"""
Test that a venue is included if only one of the opening or closing times is 00:00:00.
The view logic excludes ONLY when opening_day=00:00:00 AND closing_day=00:00:00.
"""
open_venue_slug = 'partial_zero'

# Create a venue where opening is 00:00:00 but closing is NOT 00:00:00
self._create_venue(
slug=open_venue_slug,
opening_monday=dt_time(0, 0, 0),
closing_monday=dt_time(10, 0, 0), # Non-zero closing time
)

with freezegun.freeze_time('2023-10-23 12:00:00'): # Monday
# Act
response: Response = fixture_rest_client.get(path=self.url)

# Assert
assert status.is_success(code=response.status_code)
data = response.json()

# Expected to be included
assert len(data) == 1
assert data[0]['slug'] == open_venue_slug


class TestInformationPagesView:
def test_get_informationpage(
self,
Expand Down
18 changes: 17 additions & 1 deletion backend/samfundet/view/general_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from __future__ import annotations

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

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

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

from root.custom_classes.permission_classes import RoleProtectedOrAnonReadOnlyObjectPermissions
Expand Down Expand Up @@ -113,6 +114,21 @@ class VenueView(ModelViewSet):
queryset = Venue.objects.all()
lookup_field = 'slug'

@action(detail=False, methods=['get'])
def open_venues(self, request: Request) -> Response:
day_name = timezone.now().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)
serializer = self.get_serializer(open_venues, many=True)
return Response(serializer.data)


class ClosedPeriodView(ModelViewSet):
permission_classes = (RoleProtectedOrAnonReadOnlyObjectPermissions,)
Expand Down
16 changes: 15 additions & 1 deletion frontend/src/Components/OpeningHours/OpeningHours.module.scss
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
@use 'src/constants' as *;

@use 'src/mixins' as *;

.container {
background-color: $white;
text-align: center;
margin-bottom: 20px;
display: flex;
flex-direction: column;
align-items: center;

@include theme-dark {
background-color: $black-2;
color: $white;
}
}

.tableCell {
@include theme-dark {
border-left: 0;
border-right: 0;
}
}

.openingHoursText {
margin: 0 0.2em;
}

79 changes: 73 additions & 6 deletions frontend/src/Components/OpeningHours/OpeningHours.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,81 @@ export const Basic: Story = {
args: {
venues: [
{
id: 1,
slug: 'daglighallen',
name: 'Daglighallen',
url: 'www.google.com',
start: '2011-10-05T14:00:00.000Z',
end: '2011-10-05T17:00:00.000Z',
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: 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',
},
{
id: 3,
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',
},
{ name: 'Edgar', url: 'www.google.com', start: '2011-10-05T12:00:00.000Z', end: '2011-10-05T17:00:00.000Z' },
{ name: 'Klubben', url: 'www.google.com', start: '2011-10-05T16:00:00.000Z', end: '2011-10-05T18:00:00.000Z' },
{ name: 'Storsalen', url: 'www.google.com', start: '2011-10-05T14:00:00.000Z', end: '2011-10-05T22:00:00.000Z' },
],
},
};
Loading