Skip to content

Commit

Permalink
Polish newer features (#123)
Browse files Browse the repository at this point in the history
  • Loading branch information
turboMaCk authored and ICTGuerrilla committed Oct 14, 2023
1 parent e17a78c commit b0922a0
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 49 deletions.
2 changes: 1 addition & 1 deletion melon-head/src/App.res
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module ConfiguredApp = {
/>
/* Routing to pages */
{switch url.path {
| list{} => <Dashboard session=sessionState setSessionState api />
| list{} => <Dashboard session=sessionState setSessionState api modal />
| list{"applications"} => <Applications api />
| list{"applications", id} =>
<ApplicationDetail id={Data.Uuid.unsafeFromString(id)} api modal />
Expand Down
2 changes: 1 addition & 1 deletion melon-head/src/App/AppNavigation/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
flex-direction: column;
gap: 6px;
margin-top: 64px;
padding: 12px 6px 12px 0;
padding: 12px 6px;
}

.nav-item {
Expand Down
99 changes: 95 additions & 4 deletions melon-head/src/App/ApplicationDetail.res
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,10 @@ module Actions = {
let disabled = Form.MemberNumber.validate(memberNumber)->Option.isSome

let doAccept = _ => {
open Json
let body: Js.Json.t = Encode.object([
let body: Js.Json.t = Json.Encode.object([
(
"member_number",
Encode.option(Encode.int, memberNumber->Option.flatMap(Int.fromString)),
Json.Encode.option(Json.Encode.int, memberNumber->Option.flatMap(Int.fromString)),
),
])
let path = "/applications/" ++ Uuid.toString(id) ++ "/accept"
Expand Down Expand Up @@ -532,6 +531,90 @@ module Actions = {
}
}

let viewMessage = (status, ~reject, ~resend) => {
open ApplicationData

switch status {
| Success(Unverified) =>
<Message.Warning>
<Message.Title> {React.string("Email was not verified yet!")} </Message.Title>
<p>
{React.string(
"This application is in `Verification Pending` status which means it was succefully submitted but applicant never clicked on verify link in the email.",
)}
</p>
<p>
<strong> {React.string("These are the recommended steps to take:")} </strong>
</p>
<ol>
<li>
{React.string(
"Check when this application was submitted and when the confirmation email was sent using `Metadata` tab.",
)}
</li>
<li>
{React.string(
"If application is very recent and there is an entry for when email was sent it might be good to just give applicant more time to verify it.",
)}
</li>
<li>
{React.string(
"If we miss information about email being sent that is most likely an issue on our side. Try to ",
)}
<a onClick=resend> {React.string("resend the confirmation email")} </a>
{React.string(" and check after a minute that it was sent successfully.")}
</li>
<li>
{React.string(
"If application is already few days old and there is still no confirmation might be good idea to look closer into it:",
)}
<ol>
<li>
{React.string("
You should review the information in the application and check if it's not a spam.
If it is a spam you should
")}
<strong> {React.string("report that we got a spam")} </strong>
{React.string(" and ")}
<a onClick=reject> {React.string("reject this application")} </a>
{React.string(" since it's ilegitimate.")}
</li>
<li>
{React.string("
Check if this application is not a duplicate of some other application which is verified.
Applicant might had just found a mistake in this application and decided to create a new one.
If that's the case you should just
")}
<a onClick=reject> {React.string("reject this version of application")} </a>
{React.string(".")}
</li>
<li>
{React.string("
If everything looks legitimate but you still don't see a verification you can try to
")}
<a onClick=resend> {React.string("re-send the verification email again")} </a>
{React.string("
if it looks like there is no problem with the email address.
If that doesn't help it might be a good idea to ")}
<strong> {React.string("get in touch with the applicant if possible")} </strong>
{React.string(" and try to sort thigs out over phone for example.")}
</li>
<li>
{React.string("
If you're not able to get in touch with applicant and we still don't see any verification
there is probably nothing we can do but to
")}
<a onClick=reject> {React.string("reject the application")} </a>
{React.string(".")}
</li>
</ol>
</li>
</ol>
</Message.Warning>
| _ => React.null
}
}

type tabs =
| Metadata
| Checklist
Expand All @@ -557,6 +640,8 @@ let make = (~id: Uuid.t, ~api: Api.t, ~modal: Modal.Interface.t) => {
RescriptReactRouter.push("/applications")
}

let status = RemoteData.map(detail, ApplicationData.getStatus)

<Page requireAnyRole=[ListApplications, ViewApplication]>
<header className={styles["header"]}>
<a className={styles["backBtn"]} onClick=backToApplications>
Expand All @@ -573,9 +658,15 @@ let make = (~id: Uuid.t, ~api: Api.t, ~modal: Modal.Interface.t) => {
</h1>
<h2 className={styles["status"]}>
{React.string("Status:")}
<Chip.ApplicationStatus value={RemoteData.map(detail, ApplicationData.getStatus)} />
<Chip.ApplicationStatus value=status />
</h2>
</header>
{viewMessage(
status,
~reject=_ =>
modal->Modal.Interface.openModal(Actions.rejectModal(~id, ~api, ~setDetail, ~modal)),
~resend=_ => modal->Modal.Interface.openModal(Actions.resendModal(~id, ~api, ~modal)),
)}
<div className={styles["personalInfo"]}>
<DataGrid layout data=detail />
</div>
Expand Down
25 changes: 25 additions & 0 deletions melon-head/src/App/Applications.res
Original file line number Diff line number Diff line change
Expand Up @@ -338,11 +338,36 @@ module All = {
@react.component
let make = (~api: Api.t) => {
let tabHandlers = Tabbed.make(Some(ApplicationData.Processing))
let (_, setActiveTab) = tabHandlers

let (basicStats, _, _) = api->Hook.getData(~path="/stats/basic", ~decoder=StatsData.Decode.basic)

<Page requireAnyRole=[ListApplications]>
<Page.Title> {React.string("Applications")} </Page.Title>
{switch basicStats {
| Success({unverified}) =>
if unverified > 0 {
<Message.Warning>
<Message.Title> {React.string("Some applicants might be stuck..")} </Message.Title>
<p> {React.string("Some applications did not pass email verification step yet.")} </p>
<p>
{React.string("
This might be fine since applicants can always verify email later.
But it also can be the case that some applicants didn't receive the email
or missed the notice about verification altogether.
It might be a good idea to
")}
<a onClick={_ => setActiveTab(_ => Some(ApplicationData.Unverified))}>
{React.string("check the unverified applications")}
</a>
{React.string(" and make sure this is not the case.")}
</p>
</Message.Warning>
} else {
React.null
}
| _ => React.null
}}
<div className={styles["mainContent"]}>
<Tabbed.Tabs>
<Tabbed.Tab value={Some(ApplicationData.Processing)} handlers={tabHandlers}>
Expand Down
44 changes: 32 additions & 12 deletions melon-head/src/App/Dashboard.res
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ let statusRows: array<RowBasedTable.row<Api.status>> = [
]

@react.component
let make = (~session: Api.webData<Session.t>, ~setSessionState, ~api: Api.t) => {
let make = (
~session: Api.webData<Session.t>,
~setSessionState,
~api: Api.t,
~modal: Modal.Interface.t,
) => {
let (basicStats, _, _) = api->Hook.getData(~path="/stats/basic", ~decoder=StatsData.Decode.basic)
let (status, _, _) = api->Hook.getData(~path="/status", ~decoder=Api.Decode.status)

Expand Down Expand Up @@ -86,6 +91,11 @@ let make = (~session: Api.webData<Session.t>, ~setSessionState, ~api: Api.t) =>
RescriptReactRouter.push("/members/" ++ uuid->Data.Uuid.toString)
}

let createMember = _ => {
// TODO: once we have stats for members they should be refreshed there
modal->Modal.Interface.openModal(Members.newMemberModal(~api, ~modal, ~refreshMembers=_ => ()))
}

<Page>
<Page.Title> {React.string("Dashboard")} </Page.Title>
<div className={styles["welcome"]}>
Expand All @@ -98,16 +108,18 @@ let make = (~session: Api.webData<Session.t>, ~setSessionState, ~api: Api.t) =>
| Success(None) =>
<Message.Warning>
<Message.Title>
{React.string("Your account is not paired with any member!")}
<p> {React.string("Your account is not paired with any member!")} </p>
</Message.Title>
<p>
{React.string(
"Some functions won't be accessible unless you pair your account. Just be aware that you might need to create member if it doesn't exist yet.",
"Some functions won't be accessible unless you pair your account. Just be aware that you might need to ",
)}
<a onClick=createMember> {React.string("create a new member")} </a>
{React.string(" if it doesn't exist yet.")}
</p>
<p>
{React.string(
"If you're not member but administrator you can safely ignore this message. Fuctions which require membership won't be available to you.",
"If you're not a member, but an administrator, you can safely ignore this message. Fuctions which require membership won't be available to you.",
)}
</p>
<Message.ButtonPanel>
Expand All @@ -120,20 +132,28 @@ let make = (~session: Api.webData<Session.t>, ~setSessionState, ~api: Api.t) =>
)}
</Button>
</Message.ButtonPanel>
{switch error {
| None => React.null
| Some(err) =>
<Message.Error>
<Message.Title>
{React.string("This didin't work as you would wish for...")}
</Message.Title>
{React.string(err->Api.showError)}
</Message.Error>
}}
</Message.Warning>
| Success(Some(uuid)) =>
<Message.Info>
{React.string("Your account is paired with member id ")}
<a className={styles["memberLink"]} onClick={_ => openMember(uuid)}>
{React.string(Data.Uuid.toString(uuid))}
</a>
<p>
{React.string("Your account is paired with member id ")}
<a className={styles["memberLink"]} onClick={_ => openMember(uuid)}>
{React.string(Data.Uuid.toString(uuid))}
</a>
</p>
</Message.Info>
| _ => React.null
}}
{switch error {
| None => React.null
| Some(err) => <Message.Error> {React.string(err->Api.showError)} </Message.Error>
}}
</div>
<div className={styles["statsGrid"]}>
<div className={styles["gridItem"]}>
Expand Down
13 changes: 10 additions & 3 deletions melon-head/src/App/Members.res
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,14 @@ module NewMember = {
value=newMember.email
onInput={email => setNewMember(m => {...m, email})}
/>
<Form.LanguageSelect />
<Form.Field>
<Form.Label>
{React.string("Language")}
<Form.LanguageSelect
value=newMember.language onChange={language => setNewMember(m => {...m, language})}
/>
</Form.Label>
</Form.Field>
<Form.TextField
label="First Name"
placeholder="Jane"
Expand Down Expand Up @@ -99,8 +106,8 @@ module NewMember = {
<Form.TextField
label="Postal Code"
placeholder="E1 0AA"
value=newMember.city
onInput={city => setNewMember(m => {...m, city})}
value=newMember.postalCode
onInput={postalCode => setNewMember(m => {...m, postalCode})}
/>
<Button.Panel>
<Button
Expand Down
3 changes: 2 additions & 1 deletion melon-head/src/App/Page/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
overflow: auto;
max-width: 100%;
background: var(--color2);
border-top-left-radius: 12px;
}

.title {
display: flex;
align-items: center;
flex-shrink: 0;
flex-grow: 0;
gap: 6px;
font-size: 24px;
font-weight: 700;
Expand Down
8 changes: 6 additions & 2 deletions melon-head/src/App/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ $colors-light: (
color2: #ffffff,
color3: #0d3945,
color4: #109AC0,
color5: #a63ded,
color5: #e7ad00,
color6: #00c49f,
color7: #FF5C93,
);
Expand Down Expand Up @@ -38,6 +38,7 @@ $colors-light: (

:root {
@include generate_colors($colors-light);

--page-background: linear-gradient(233deg, rgb(35,152,168) 0%, rgb(0,192,213) 42%, rgb(35,112,168) 100%);
--secondary-background: linear-gradient(233deg, rgba(56, 152, 190, .5) 0%, rgba(24, 101, 157, .5) 100%);
--emphasis-light-overlay: rgba(var(--rgb_color2), 0.1);
Expand All @@ -51,6 +52,10 @@ $colors-light: (
--border-color: #17a6b8;
--error-color: #{map.get($colors-light, color7)};
--error-bgcolor: #{color.mix(map.get($colors-light, color7), map.get($colors-light, color2), $weight: 15%)};
--warning-color: #{map.get($colors-light, color5)};
--warning-bgcolor: #{color.mix(map.get($colors-light, color5), map.get($colors-light, color2), $weight: 15%)};
--info-color: #{map.get($colors-light, color4)};
--info-bgcolor: #{color.mix(map.get($colors-light, color4), map.get($colors-light, color2), $weight: 15%)};
}

.root {
Expand All @@ -59,7 +64,6 @@ $colors-light: (
height: 100%;
overflow: hidden;
background: var(--page-background);
padding-left: 6px;
}

.main-container {
Expand Down
9 changes: 9 additions & 0 deletions melon-head/src/Data/Data.res
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,12 @@ module Decode = {
createdAt: field.required(. "created_at", date),
})
}

module Encode = {
open Json.Encode

let day = (date: Js.Date.t): Js.Json.t => {
let str = Js.Date.toJSONUnsafe(date)->Js.String.slice(~from=0, ~to_=10)
string(str)
}
}
2 changes: 1 addition & 1 deletion melon-head/src/Data/MemberData.res
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ module Encode = {
("last_name", strOption(newMember.lastName)),
("email", strOption(newMember.email)),
("phone_number", strOption(newMember.phoneNumber)),
("date_of_birth", option(date, newMember.dateOfBirth)),
("date_of_birth", option(Data.Encode.day, newMember.dateOfBirth)),
("address", strOption(newMember.address)),
("city", strOption(newMember.city)),
("postal_code", strOption(newMember.city)),
Expand Down
8 changes: 4 additions & 4 deletions melon-head/src/Widgets/Button/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@

.cta {
border: 1px solid var(--border-color);
background: var(--background-color);
color: var(--color3);
background: var(--border-color);
color: var(--color2);

&:hover {
background: var(--border-color);
color: var(--color2);
background: var(--background-color);
color: var(--color3);
}
}

Expand Down
Loading

0 comments on commit b0922a0

Please sign in to comment.