diff --git a/backend/clubs/migrations/0115_club_beta_historicalclub_beta.py b/backend/clubs/migrations/0115_club_beta_historicalclub_beta.py new file mode 100644 index 000000000..832c7afdf --- /dev/null +++ b/backend/clubs/migrations/0115_club_beta_historicalclub_beta.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.4 on 2024-10-05 02:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("clubs", "0114_alter_advisor_public"), + ] + + operations = [ + migrations.AddField( + model_name="club", + name="beta", + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name="historicalclub", + name="beta", + field=models.BooleanField(default=False), + ), + ] diff --git a/backend/clubs/models.py b/backend/clubs/models.py index 36cc23044..2c38e28e8 100644 --- a/backend/clubs/models.py +++ b/backend/clubs/models.py @@ -294,6 +294,7 @@ class Club(models.Model): code = models.SlugField(max_length=255, unique=True, db_index=True) active = models.BooleanField(default=False) + beta = models.BooleanField(default=False) # opts club into all beta features name = models.CharField(max_length=255) subtitle = models.CharField(blank=True, max_length=255) terms = models.CharField(blank=True, max_length=1024) diff --git a/backend/clubs/serializers.py b/backend/clubs/serializers.py index 444dfc9ef..015a4c7da 100644 --- a/backend/clubs/serializers.py +++ b/backend/clubs/serializers.py @@ -1502,6 +1502,11 @@ def save(self): """ Override save in order to replace code with slugified name if not specified. """ + if "beta" in self.validated_data: + raise serializers.ValidationError( + "The beta field is not allowed to be set by clubs." + ) + # remove any spaces from the name if "name" in self.validated_data: self.validated_data["name"] = self.validated_data["name"].strip() @@ -1704,6 +1709,7 @@ class Meta(ClubListSerializer.Meta): "approved_by", "approved_comment", "badges", + "beta", "created_at", "description", "events", diff --git a/frontend/components/ClubEditPage/EventsCard.tsx b/frontend/components/ClubEditPage/EventsCard.tsx index 1a741614f..cdd765d91 100644 --- a/frontend/components/ClubEditPage/EventsCard.tsx +++ b/frontend/components/ClubEditPage/EventsCard.tsx @@ -401,7 +401,7 @@ const CreateContainer = styled.div` align-items: center; ` -const CreateTickets = ({ event }: { event: ClubEvent }) => { +const CreateTickets = ({ event, club }: { event: ClubEvent; club: Club }) => { const [show, setShow] = useState(false) const showModal = () => setShow(true) const hideModal = () => setShow(false) @@ -431,7 +431,11 @@ const CreateTickets = ({ event }: { event: ClubEvent }) => { closeModal={hideModal} marginBottom={false} > - + )} @@ -476,7 +480,7 @@ export default function EventsCard({ club }: EventsCardProps): ReactElement { }} /> - +
diff --git a/frontend/components/ClubEditPage/TicketsModal.tsx b/frontend/components/ClubEditPage/TicketsModal.tsx index 7eec51535..12553498e 100644 --- a/frontend/components/ClubEditPage/TicketsModal.tsx +++ b/frontend/components/ClubEditPage/TicketsModal.tsx @@ -14,7 +14,7 @@ import { } from '../../constants/colors' import { BORDER_RADIUS } from '../../constants/measurements' import { BODY_FONT } from '../../constants/styles' -import { ClubEvent } from '../../types' +import { Club, ClubEvent } from '../../types' import { doApiRequest } from '../../utils' import CoverPhoto from '../EventPage/CoverPhoto' @@ -56,6 +56,7 @@ const notify = ( type TicketItemProps = { ticket: Ticket + club: Club onChange?: (ticket: Ticket) => void onDelete?: () => void deletable: boolean @@ -63,6 +64,7 @@ type TicketItemProps = { const TicketItem: React.FC = ({ ticket: propTicket, + club, onChange, onDelete, deletable, @@ -122,7 +124,7 @@ const TicketItem: React.FC = ({ className="input" value={ticket.price ?? ''} placeholder="Ticket Price" - disabled={!TICKETING_PAYMENT_ENABLED} + disabled={!TICKETING_PAYMENT_ENABLED && !club.beta} onChange={(e) => { const price = e.target.value setTicket({ ...ticket, price }) @@ -221,9 +223,11 @@ type Ticket = { const TicketsModal = ({ event, + club, onSuccessfulSubmit, }: { event: ClubEvent + club: Club onSuccessfulSubmit: () => void }): ReactElement => { const { large_image_url, image_url, club_name, name, id } = event @@ -333,6 +337,7 @@ const TicketsModal = ({ 1} onChange={(newTicket) => { setTickets((t) => diff --git a/frontend/types.ts b/frontend/types.ts index 947567c10..00a343f2e 100644 --- a/frontend/types.ts +++ b/frontend/types.ts @@ -167,6 +167,7 @@ export interface Club { approved_comment: string | null available_virtually: boolean badges: Badge[] + beta: boolean code: string description: string email: string