Skip to content

Commit

Permalink
User gender (backend) (#437)
Browse files Browse the repository at this point in the history
* feat: wrote DB migration for user gender

* fix: removed 'Other' gender

* feat: fully implemented user gender in backend

* fix: set user gender to non-nullable

* dev(frontend): added pronouns and gender field on signup

* fix: re-arranged gender options

* fix: user signup works with gender

---------

Co-authored-by: m4ch374 <[email protected]>
  • Loading branch information
dhj03 and m4ch374 authored Sep 20, 2023
1 parent 92f0244 commit 3ebf36e
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 4 deletions.
4 changes: 4 additions & 0 deletions backend/migrations/2023-06-07-042751_user_gender/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ALTER TABLE users
DROP COLUMN gender;

DROP TYPE user_gender;
4 changes: 4 additions & 0 deletions backend/migrations/2023-06-07-042751_user_gender/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE TYPE user_gender AS ENUM ('Female', 'Male', 'Unspecified');

ALTER TABLE users
ADD COLUMN gender user_gender DEFAULT 'Unspecified' NOT NULL;
9 changes: 8 additions & 1 deletion backend/seed_data/src/seed.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(unused_variables)]

use backend::database::models::*;
use backend::database::schema::{AdminLevel, ApplicationStatus};
use backend::database::schema::{AdminLevel, ApplicationStatus, UserGender};
use backend::images::{save_image, try_decode_bytes};
use chrono::naive::NaiveDate;
use diesel::pg::PgConnection;
Expand All @@ -24,6 +24,7 @@ pub fn seed() {
display_name: "Shrey Somaiya".to_string(),
degree_name: "B. CompSci".to_string(),
degree_starting_year: 2019,
gender: UserGender::Unspecified,
superuser: true,
},
NewUser {
Expand All @@ -32,6 +33,7 @@ pub fn seed() {
display_name: "Fake User".to_string(),
degree_name: "B. CompSci".to_string(),
degree_starting_year: 2019,
gender: UserGender::Unspecified,
superuser: false,
},
NewUser {
Expand All @@ -40,6 +42,7 @@ pub fn seed() {
display_name: "Michael Gribben".to_string(),
degree_name: "B. Eng (Software)".to_string(),
degree_starting_year: 2019,
gender: UserGender::Male,
superuser: false,
},
NewUser {
Expand All @@ -48,6 +51,7 @@ pub fn seed() {
display_name: "Giuliana Debellis".to_string(),
degree_name: "B. CompSci".to_string(),
degree_starting_year: 2020,
gender: UserGender::Female,
superuser: false,
},
NewUser {
Expand All @@ -56,6 +60,7 @@ pub fn seed() {
display_name: "Lachlan Ting".to_string(),
degree_name: "B. CompSci".to_string(),
degree_starting_year: 2019,
gender: UserGender::Male,
superuser: false,
},
NewUser {
Expand All @@ -64,6 +69,7 @@ pub fn seed() {
display_name: "Hayes Choi".to_string(),
degree_name: "B. CompSci".to_string(),
degree_starting_year: 2020,
gender: UserGender::Male,
superuser: false,
},
NewUser {
Expand All @@ -72,6 +78,7 @@ pub fn seed() {
display_name: "Clarence Feng".to_string(),
degree_name: "B. CompSci".to_string(),
degree_starting_year: 2020,
gender: UserGender::Male,
superuser: false,
},
];
Expand Down
3 changes: 3 additions & 0 deletions backend/server/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::error::JsonErr;
use crate::{
database::{
models::{NewUser, User},
schema::{UserGender},
Database,
},
state::ApiState,
Expand Down Expand Up @@ -279,6 +280,7 @@ pub struct SignUpBody {
display_name: String,
degree_name: String,
degree_starting_year: u32,
gender: UserGender,
}

#[derive(Serialize)]
Expand Down Expand Up @@ -347,6 +349,7 @@ pub async fn signup(
display_name: body.display_name.to_string(),
degree_name: body.degree_name.to_string(),
degree_starting_year: body.degree_starting_year as i32,
gender: body.gender,
superuser: User::get_number(conn) == 0,
};

Expand Down
5 changes: 3 additions & 2 deletions backend/server/src/database/models.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use crate::images::{get_http_image_path, ImageLocation};

use super::schema::AdminLevel;
use super::schema::ApplicationStatus;
use super::schema::{
answers, applications, campaigns, comments, organisation_users, organisations, questions,
ratings, roles, users,
};
use super::schema::{AdminLevel, ApplicationStatus, UserGender};
use chrono::NaiveDateTime;
use chrono::Utc;
use diesel::prelude::*;
Expand All @@ -24,6 +23,7 @@ pub struct User {
pub display_name: String,
pub degree_name: String,
pub degree_starting_year: i32,
pub gender: UserGender,
pub superuser: bool,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
Expand All @@ -50,6 +50,7 @@ pub struct NewUser {
pub display_name: String,
pub degree_name: String,
pub degree_starting_year: i32,
pub gender: UserGender,
pub superuser: bool,
}

Expand Down
12 changes: 12 additions & 0 deletions backend/server/src/database/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ impl AdminLevel {
}
}

#[derive(Debug, DbEnum, PartialEq, Serialize, Deserialize, Clone, Copy)]
#[DbValueStyle = "PascalCase"]
pub enum UserGender {
Female,
Male,
Unspecified,
}

table! {
answers (id) {
id -> Int4,
Expand Down Expand Up @@ -142,13 +150,17 @@ table! {
}

table! {
use diesel::sql_types::*;
use super::UserGenderMapping;

users (id) {
id -> Int4,
email -> Text,
zid -> Text,
display_name -> Text,
degree_name -> Text,
degree_starting_year -> Int4,
gender -> UserGenderMapping,
superuser -> Bool,
created_at -> Timestamp,
updated_at -> Timestamp,
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {
Role,
RoleApplications,
RoleInput,
UserGender,
UserResponse,
} from "../types/api";

Expand All @@ -39,11 +40,13 @@ export const doSignup = async ({
degree_name,
zid,
starting_year,
gender,
}: {
name: string;
degree_name: string;
zid: string;
starting_year: number;
gender: UserGender;
}) =>
API.request<{ token: string }>({
method: "POST",
Expand All @@ -54,6 +57,7 @@ export const doSignup = async ({
display_name: name,
degree_starting_year: starting_year,
degree_name,
gender,
},
});

Expand Down
17 changes: 17 additions & 0 deletions frontend/src/pages/signup/SignupGenderSelection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import tw from "twin.macro";

import type { ReactNode } from "react";
import type React from "react";

const Select = tw.select`
form-select w-96 rounded-md
border-gray-300 shadow-sm
transition hocus:border-blue-300 focus:(ring ring-blue-200/50)
`;

const Label = tw.label`flex flex-col`;
const LabelText: React.FC<{ children: ReactNode }> = ({ children }) => (
<span tw="text-gray-700">{children}</span>
);

export default Object.assign(Select, { Label, LabelText });
35 changes: 34 additions & 1 deletion frontend/src/pages/signup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,28 @@ import Input from "components/Input";
import { doSignup } from "../../api";
import { getStore, setStore } from "../../utils";

import Select from "./SignupGenderSelection";

import type { UserGender } from "types/api";

// I had to do it
/* eslint-disable @typescript-eslint/naming-convention */
type TFormData = {
zid: string;
name: string;
degree_name: string;
starting_year: number;
gender: UserGender;
};
/* eslint-enable @typescript-eslint/naming-convention */

const Signup = () => {
const [formData, setFormData] = useState({
const [formData, setFormData] = useState<TFormData>({
zid: "",
name: getStore("name") || "",
degree_name: "",
starting_year: new Date().getFullYear(),
gender: "Unspecified",
});

const navigate = useNavigate();
Expand Down Expand Up @@ -99,6 +115,23 @@ const Signup = () => {
max={new Date().getFullYear() + 10}
/>
</Input.Label>

<Select.Label>
<Select.LabelText>Gender</Select.LabelText>
<Select
defaultValue={formData.gender}
onChange={(e) => {
setFormData({
...formData,
gender: e.target.value as UserGender, // small hack
});
}}
>
<option value="Female">Female</option>
<option value="Male">Male</option>
<option value="Unspecified">Other / Prefer not to say</option>
</Select>
</Select.Label>
</div>

<Button tw="justify-center font-medium" type="submit">
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ export type OrganisationInfo = {
campaigns: CampaignInfo[];
};

// Based
export type UserGender = "Male" | "Female" | "Unspecified";

// Will add ticket to reflect new response
export type UserResponse = {
email: string;
zid: string;
Expand Down

0 comments on commit 3ebf36e

Please sign in to comment.