feat: image url migration

registrations can now store image urls, which will be shown at view.html
This commit is contained in:
2025-06-02 03:01:10 +02:00
parent 4a82822d64
commit f7583738d7
12 changed files with 675 additions and 14 deletions

View File

@@ -1,4 +1,4 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using WebApp.Entities; using WebApp.Entities;
namespace WebApp.DTOs; namespace WebApp.DTOs;
@@ -8,6 +8,7 @@ public record class EventCreateDto
( (
[Required][StringLength(50)] string Title, [Required][StringLength(50)] string Title,
[StringLength(500)] string Description, [StringLength(500)] string Description,
string? ImageURL,
[Required][StringLength(100)] string Location, [Required][StringLength(100)] string Location,
[Required] DateTime? EventDate, [Required] DateTime? EventDate,
ICollection<EventSkill> EventSkills ICollection<EventSkill> EventSkills

View File

@@ -11,6 +11,7 @@ public record class EventDetailsDto
[Required] public string? OrganisationName { get; set; } [Required] public string? OrganisationName { get; set; }
[Required][StringLength(50)] public string Title { get; set; } [Required][StringLength(50)] public string Title { get; set; }
[StringLength(500)] public string Description { get; set; } [StringLength(500)] public string Description { get; set; }
public string? ImageURL { get; set; }
[Required][StringLength(100)] public string Location { get; set; } [Required][StringLength(100)] public string Location { get; set; }
[Required] public DateTime? EventDate { get; set; } [Required] public DateTime? EventDate { get; set; }
//ICollection<EventSkill> EventSkills, //ICollection<EventSkill> EventSkills,

View File

@@ -10,6 +10,7 @@ public record class EventSummaryDto {
[Required] public int OrganisationId { get; set; } [Required] public int OrganisationId { get; set; }
[Required] [StringLength(50)] public string Title { get; set; } [Required] [StringLength(50)] public string Title { get; set; }
[StringLength(500)] public string Description { get; set; } [StringLength(500)] public string Description { get; set; }
public string? ImageURL { get; set; }
[Required] [StringLength(100)] public string Location { get; set; } [Required] [StringLength(100)] public string Location { get; set; }
[Required] public DateTime? EventDate { get; set; } [Required] public DateTime? EventDate { get; set; }
public ICollection<SkillSummaryDto> EventSkills { get; set; } public ICollection<SkillSummaryDto> EventSkills { get; set; }

View File

@@ -10,6 +10,7 @@ public record class EventSummaryNoErDto(
[Required] int OrganisationId, [Required] int OrganisationId,
[Required][StringLength(50)] string Title, [Required][StringLength(50)] string Title,
[StringLength(500)] string Description, [StringLength(500)] string Description,
string? ImageURL,
[Required][StringLength(100)] string Location, [Required][StringLength(100)] string Location,
[Required] DateTime? EventDate, [Required] DateTime? EventDate,
ICollection<EventSkill> EventSkills ICollection<EventSkill> EventSkills

View File

@@ -1,4 +1,4 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using WebApp.Entities; using WebApp.Entities;
namespace WebApp.DTOs; namespace WebApp.DTOs;
@@ -8,6 +8,7 @@ public record class EventUpdateDto
( (
[Required][StringLength(50)] string Title, [Required][StringLength(50)] string Title,
[StringLength(500)] string Description, [StringLength(500)] string Description,
string? ImageURL,
[Required][StringLength(100)] string Location, [Required][StringLength(100)] string Location,
[Required] DateTime? EventDate, [Required] DateTime? EventDate,
ICollection<EventSkill> EventSkills ICollection<EventSkill> EventSkills

View File

@@ -5,15 +5,10 @@ using WebApp.Entities;
namespace WebApp.Endpoints; namespace WebApp.Endpoints;
public class GeneralUseHelpers public class GeneralUseHelpers(ApplicationDbContext context)
{ {
private readonly ApplicationDbContext _context; private readonly ApplicationDbContext _context = context;
public GeneralUseHelpers(ApplicationDbContext context)
{
_context = context;
}
async public Task<Token?> FindTokenFromString(string token_str) async public Task<Token?> FindTokenFromString(string token_str)
{ {
@@ -129,6 +124,7 @@ public class GeneralUseHelpers
OrganisationName = e.Organisation!.Name, OrganisationName = e.Organisation!.Name,
Title = e.Title, Title = e.Title,
Description = e.Description ?? "", Description = e.Description ?? "",
ImageURL = e.ImageURL,
Location = e.Location, Location = e.Location,
EventDate = e.EventDate, EventDate = e.EventDate,
EventSkills = e EventSkills = e
@@ -175,6 +171,7 @@ public class GeneralUseHelpers
Organisation = e.Organisation!.Name, Organisation = e.Organisation!.Name,
Title = e.Title, Title = e.Title,
Description = e.Description ?? "", Description = e.Description ?? "",
ImageURL = e.ImageURL,
Location = e.Location, Location = e.Location,
EventDate = e.EventDate, EventDate = e.EventDate,
EventSkills = e EventSkills = e

View File

@@ -1,4 +1,4 @@
namespace WebApp.Entities namespace WebApp.Entities
{ {
public class Event public class Event
{ {
@@ -6,6 +6,7 @@
public int OrganisationId { get; set; } public int OrganisationId { get; set; }
public required string Title { get; set; } public required string Title { get; set; }
public string? Description { get; set; } public string? Description { get; set; }
public string? ImageURL { get; set; }
public required string Location { get; set; } public required string Location { get; set; }
public required DateTime EventDate { get; set; } public required DateTime EventDate { get; set; }

View File

@@ -35,8 +35,8 @@ public static class EventMapping
public static EventSummaryDto ToEventSummaryDto(this Event myEvent) public static EventSummaryDto ToEventSummaryDto(this Event myEvent)
{ {
List<SkillSummaryDto> ssdto = new List<SkillSummaryDto>(); List<SkillSummaryDto> ssdto = [];
List<EventRegistrationDto> erdto = new List<EventRegistrationDto>(); List<EventRegistrationDto> erdto = [];
foreach (EventSkill es in myEvent.EventSkills) foreach (EventSkill es in myEvent.EventSkills)
{ {
@@ -69,6 +69,7 @@ public static class EventMapping
myEvent.OrganisationId, myEvent.OrganisationId,
myEvent.Title, myEvent.Title,
myEvent.Description ?? "", myEvent.Description ?? "",
myEvent.ImageURL,
myEvent.Location, myEvent.Location,
myEvent.EventDate, myEvent.EventDate,
myEvent.EventSkills myEvent.EventSkills
@@ -88,8 +89,8 @@ public static class EventMapping
public static EventDetailsDto ToEventDetailsDto(this Event myEvent) public static EventDetailsDto ToEventDetailsDto(this Event myEvent)
{ {
List<SkillSummaryDto> ssdto = new List<SkillSummaryDto>(); List<SkillSummaryDto> ssdto = [];
List<EventRegistrationDto> erdto = new List<EventRegistrationDto>(); List<EventRegistrationDto> erdto = [];
foreach (EventSkill es in myEvent.EventSkills) foreach (EventSkill es in myEvent.EventSkills)
{ {

View File

@@ -0,0 +1,625 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using WebApp.Data;
#nullable disable
namespace WebApp.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20250602005444_EventImageURL")]
partial class EventImageURL
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.3")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("WebApp.Entities.Event", b =>
{
b.Property<int>("EventId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("EventId"));
b.Property<string>("Description")
.HasColumnType("text");
b.Property<DateTime>("EventDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ImageURL")
.HasColumnType("text");
b.Property<string>("Location")
.IsRequired()
.HasColumnType("text");
b.Property<int>("OrganisationId")
.HasColumnType("integer");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.HasKey("EventId");
b.HasIndex("OrganisationId");
b.ToTable("Events");
});
modelBuilder.Entity("WebApp.Entities.EventRegistration", b =>
{
b.Property<int>("UserId")
.HasColumnType("integer");
b.Property<int>("EventId")
.HasColumnType("integer");
b.Property<DateTime>("RegisteredAt")
.HasColumnType("timestamp with time zone");
b.HasKey("UserId", "EventId");
b.HasIndex("EventId");
b.ToTable("EventRegistrations");
});
modelBuilder.Entity("WebApp.Entities.EventSkill", b =>
{
b.Property<int>("EventId")
.HasColumnType("integer");
b.Property<int>("SkillId")
.HasColumnType("integer");
b.HasKey("EventId", "SkillId");
b.HasIndex("SkillId");
b.ToTable("EventSkills");
});
modelBuilder.Entity("WebApp.Entities.Message", b =>
{
b.Property<int>("MessageId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("MessageId"));
b.Property<string>("Content")
.HasColumnType("text");
b.Property<int>("EventType")
.HasColumnType("integer");
b.Property<bool>("IsMsgFromVolunteer")
.HasColumnType("boolean");
b.Property<DateTime>("IsoDate")
.HasColumnType("timestamp with time zone");
b.Property<int>("OrganizationId")
.HasColumnType("integer");
b.Property<int>("VolunteerId")
.HasColumnType("integer");
b.HasKey("MessageId");
b.ToTable("Messages");
});
modelBuilder.Entity("WebApp.Entities.MessageActivity", b =>
{
b.Property<int>("Sender")
.HasColumnType("integer");
b.Property<int>("Recipient")
.HasColumnType("integer");
b.Property<DateTime>("RecipientLastActive")
.HasColumnType("timestamp with time zone");
b.HasKey("Sender", "Recipient");
b.ToTable("MessagesActivities");
});
modelBuilder.Entity("WebApp.Entities.Organisation", b =>
{
b.Property<int>("OrganisationId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("OrganisationId"));
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("UserId")
.HasColumnType("integer");
b.Property<string>("Website")
.HasColumnType("text");
b.HasKey("OrganisationId");
b.HasIndex("UserId");
b.ToTable("Organisations");
});
modelBuilder.Entity("WebApp.Entities.Skill", b =>
{
b.Property<int>("SkillId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SkillId"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("SkillId");
b.ToTable("Skills");
});
modelBuilder.Entity("WebApp.Entities.Token", b =>
{
b.Property<int>("TokenId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("TokenId"));
b.Property<int>("UserId")
.HasColumnType("integer");
b.Property<DateTime>("ValidUntil")
.HasColumnType("timestamp with time zone");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("TokenId");
b.HasIndex("UserId");
b.ToTable("Tokens");
});
modelBuilder.Entity("WebApp.Entities.User", b =>
{
b.Property<int>("UserId")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("UserId"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.HasColumnType("text");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsOrganisation")
.HasColumnType("boolean");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.HasColumnType("text");
b.HasKey("UserId");
b.ToTable("WebUsers");
});
modelBuilder.Entity("WebApp.Entities.VolunteerSkill", b =>
{
b.Property<int>("UserId")
.HasColumnType("integer");
b.Property<int>("SkillId")
.HasColumnType("integer");
b.HasKey("UserId", "SkillId");
b.HasIndex("SkillId");
b.ToTable("VolunteerSkills");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("WebApp.Entities.Event", b =>
{
b.HasOne("WebApp.Entities.Organisation", "Organisation")
.WithMany("Events")
.HasForeignKey("OrganisationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Organisation");
});
modelBuilder.Entity("WebApp.Entities.EventRegistration", b =>
{
b.HasOne("WebApp.Entities.Event", "Event")
.WithMany("EventRegistrations")
.HasForeignKey("EventId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("WebApp.Entities.User", "User")
.WithMany("EventRegistrations")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Event");
b.Navigation("User");
});
modelBuilder.Entity("WebApp.Entities.EventSkill", b =>
{
b.HasOne("WebApp.Entities.Event", "Event")
.WithMany("EventSkills")
.HasForeignKey("EventId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("WebApp.Entities.Skill", "Skill")
.WithMany("EventSkills")
.HasForeignKey("SkillId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Event");
b.Navigation("Skill");
});
modelBuilder.Entity("WebApp.Entities.Organisation", b =>
{
b.HasOne("WebApp.Entities.User", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("WebApp.Entities.Token", b =>
{
b.HasOne("WebApp.Entities.User", null)
.WithMany("Tokens")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("WebApp.Entities.VolunteerSkill", b =>
{
b.HasOne("WebApp.Entities.Skill", "Skill")
.WithMany("VolunteerSkills")
.HasForeignKey("SkillId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("WebApp.Entities.User", "User")
.WithMany("VolunteerSkills")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Skill");
b.Navigation("User");
});
modelBuilder.Entity("WebApp.Entities.Event", b =>
{
b.Navigation("EventRegistrations");
b.Navigation("EventSkills");
});
modelBuilder.Entity("WebApp.Entities.Organisation", b =>
{
b.Navigation("Events");
});
modelBuilder.Entity("WebApp.Entities.Skill", b =>
{
b.Navigation("EventSkills");
b.Navigation("VolunteerSkills");
});
modelBuilder.Entity("WebApp.Entities.User", b =>
{
b.Navigation("EventRegistrations");
b.Navigation("Tokens");
b.Navigation("VolunteerSkills");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace WebApp.Migrations
{
/// <inheritdoc />
public partial class EventImageURL : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "ImageURL",
table: "Events",
type: "text",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ImageURL",
table: "Events");
}
}
}

View File

@@ -232,6 +232,9 @@ namespace WebApp.Migrations
b.Property<DateTime>("EventDate") b.Property<DateTime>("EventDate")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("ImageURL")
.HasColumnType("text");
b.Property<string>("Location") b.Property<string>("Location")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");

View File

@@ -74,6 +74,7 @@
<script type="module" src="/js/generalUseHelpers.js"></script> <script type="module" src="/js/generalUseHelpers.js"></script>
<script type="module" src="/js/auth.js"></script> <script type="module" src="/js/auth.js"></script>
</div>
</body> </body>