1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-08-07 14:15:18 +02:00

feat: add measurement system field to CustomUser model and update related serializers, migrations, and UI components

This commit is contained in:
Sean Morley 2025-08-05 11:53:02 -04:00
parent 2af78e0a53
commit 31630de4fd
9 changed files with 76 additions and 21 deletions

View file

@ -82,11 +82,11 @@ from users.models import CustomUser
class CustomUserAdmin(UserAdmin):
model = CustomUser
list_display = ['username', 'is_staff', 'is_active', 'image_display']
list_display = ['username', 'is_staff', 'is_active', 'image_display', 'measurement_system']
readonly_fields = ('uuid',)
search_fields = ('username',)
fieldsets = UserAdmin.fieldsets + (
(None, {'fields': ('profile_pic', 'uuid', 'public_profile', 'disable_password')}),
(None, {'fields': ('profile_pic', 'uuid', 'public_profile', 'disable_password', 'measurement_system')}),
)
def image_display(self, obj):
if obj.profile_pic:

View file

@ -0,0 +1,18 @@
# Generated by Django 5.2.2 on 2025-08-05 15:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0004_customuser_disable_password'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='measurement_system',
field=models.CharField(choices=[('metric', 'Metric'), ('imperial', 'Imperial')], default='metric', max_length=10),
),
]

View file

@ -9,6 +9,7 @@ class CustomUser(AbstractUser):
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
public_profile = models.BooleanField(default=False)
disable_password = models.BooleanField(default=False)
measurement_system = models.CharField(max_length=10, choices=[('metric', 'Metric'), ('imperial', 'Imperial')], default='metric')
def __str__(self):
return self.username

View file

@ -50,7 +50,7 @@ class UserDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
extra_fields = ['profile_pic', 'uuid', 'public_profile']
extra_fields = ['profile_pic', 'uuid', 'public_profile', 'measurement_system']
if hasattr(UserModel, 'USERNAME_FIELD'):
extra_fields.append(UserModel.USERNAME_FIELD)
@ -66,6 +66,8 @@ class UserDetailsSerializer(serializers.ModelSerializer):
extra_fields.append('is_staff')
if hasattr(UserModel, 'disable_password'):
extra_fields.append('disable_password')
if hasattr(UserModel, 'measurement_system'):
extra_fields.append('measurement_system')
fields = ['pk', *extra_fields]
read_only_fields = ('email', 'date_joined', 'is_staff', 'is_superuser', 'is_active', 'pk', 'disable_password')
@ -96,7 +98,7 @@ class CustomUserDetailsSerializer(UserDetailsSerializer):
class Meta(UserDetailsSerializer.Meta):
model = CustomUser
fields = UserDetailsSerializer.Meta.fields + ['profile_pic', 'uuid', 'public_profile', 'has_password', 'disable_password']
fields = UserDetailsSerializer.Meta.fields + ['profile_pic', 'uuid', 'public_profile', 'has_password', 'disable_password', 'measurement_system']
read_only_fields = UserDetailsSerializer.Meta.read_only_fields + ('uuid', 'has_password', 'disable_password')
@staticmethod

View file

@ -17,6 +17,7 @@ declare global {
public_profile: boolean;
has_password: boolean;
disable_password: boolean;
measurement_system: 'metric' | 'imperial';
} | null;
locale: string;
}

View file

@ -12,6 +12,7 @@ export type User = {
public_profile: boolean;
has_password: boolean;
disable_password: boolean;
measurement_system: 'metric' | 'imperial';
};
export type ContentImage = {

View file

@ -542,7 +542,9 @@
"data_override_warning_desc": "Restoring data will completely replace all existing data (that is included \t\t\t\t\t\t\t\t\t\t\t\tin the backup) in your account. This action cannot be undone.",
"select_backup_file": "Select backup file",
"data_override_acknowledge": "I acknowledge that this will override all my existing data",
"data_override_acknowledge_desc": "This action is irreversible and will replace all locations, collections, \t\t\t\t\t\t\t\t\t\t\t\t\t\tand visits in your account."
"data_override_acknowledge_desc": "This action is irreversible and will replace all locations, collections, \t\t\t\t\t\t\t\t\t\t\t\t\t\tand visits in your account.",
"use_imperial": "Use Imperial Units",
"use_imperial_desc": "Use imperial units (feet, inches, pounds) instead of metric units"
},
"collection": {
"collection_created": "Collection created successfully!",

View file

@ -129,6 +129,7 @@ export const actions: Actions = {
let last_name = formData.get('last_name') as string | null | undefined;
let profile_pic = formData.get('profile_pic') as File | null | undefined;
let public_profile = formData.get('public_profile') as string | null | undefined | boolean;
let measurement_system = formData.get('measurement_system') as string | null | undefined;
const resCurrent = await fetch(`${endpoint}/auth/user-metadata/`, {
headers: {
@ -148,6 +149,13 @@ export const actions: Actions = {
public_profile = false;
}
// Gets the boolean value of the measurement_system input checked means imperial
if (measurement_system === 'on') {
measurement_system = 'imperial';
} else {
measurement_system = 'metric';
}
let currentUser = (await resCurrent.json()) as User;
if (username === currentUser.username || !username) {
@ -178,6 +186,7 @@ export const actions: Actions = {
formDataToSend.append('profile_pic', profile_pic);
}
formDataToSend.append('public_profile', public_profile.toString());
formDataToSend.append('measurement_system', measurement_system.toString());
let csrfToken = await fetchCSRFToken();

View file

@ -515,23 +515,44 @@
accept="image/*"
/>
</div>
</div>
<div class="form-control">
<label class="label cursor-pointer justify-start gap-4">
<input
type="checkbox"
bind:checked={user.public_profile}
name="public_profile"
class="toggle toggle-primary"
/>
<div>
<span class="label-text font-medium">{$t('auth.public_profile')}</span>
<p class="text-sm text-base-content/60">
{$t('settings.public_profile_desc')}
</p>
</div>
</label>
<div class="form-control">
<label class="label cursor-pointer justify-start gap-4">
<input
type="checkbox"
bind:checked={user.public_profile}
name="public_profile"
class="toggle toggle-primary"
/>
<div>
<span class="label-text font-medium">{$t('auth.public_profile')}</span>
<p class="text-sm text-base-content/60">
{$t('settings.public_profile_desc')}
</p>
</div>
</label>
</div>
<!-- metric or imperal toggle -->
<div class="form-control">
<label class="label cursor-pointer justify-start gap-4">
<input
type="checkbox"
checked={user.measurement_system === 'imperial'}
name="measurement_system"
class="toggle toggle-primary"
on:change={() =>
(user.measurement_system =
user.measurement_system === 'metric' ? 'imperial' : 'metric')}
/>
<div>
<span class="label-text font-medium">{$t('settings.use_imperial')}</span>
<p class="text-sm text-base-content/60">
{$t('settings.use_imperial_desc')}
</p>
</div>
</label>
</div>
</div>
<button class="btn btn-primary btn-wide">