tutorbookapp / tutorbook Goto Github PK
View Code? Open in Web Editor NEWWeb app that helps schools and nonprofits connect students with expert mentors and volunteer tutors.
Home Page: https://tutorbook.org
License: Other
Web app that helps schools and nonprofits connect students with expert mentors and volunteer tutors.
Home Page: https://tutorbook.org
License: Other
Using Poppins as our default font-family
seems to be causing some issues on the taller letters in input elements (e.g. the MDC Select
, TextField
, and our own custom SubjectSelect
). As pictured below, the g
's are all cut off:
We set Poppins as the default in src/styles/global.scss
when we @use
the @material/typography
module:
@use '@material/typography' with (
$font-family: unquote('Poppins, sans-serif'),
$styles-button: (
font-size: 1.05rem,
font-weight: map.get($font-weight-values, bold),
letter-spacing: 0.0125rem,
text-transform: none,
),
$styles-headline2: (
font-size: 3.5rem,
font-weight: map.get($font-weight-values, bold),
letter-spacing: -0.125rem,
),
);
We receive this error message (due to our SubjectSelect
) whenever a subject is selected from our drop-down select menu:
index.js:1 Warning: A component is changing an uncontrolled input of type checkbox to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://fb.me/react-controlled-components
in input (created by Function)
in div (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by ForwardRef(CheckboxRoot))
in ForwardRef(CheckboxRoot) (created by withRipple(Object))
in Ripple (created by class_1)
in class_1 (created by withRipple(Object))
in withRipple(Object) (created by Function)
in Function (at subject-select.tsx:217)
in i (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by ForwardRef(IconRoot))
in ForwardRef(IconRoot) (created by Icon)
in Icon (created by Function)
in Function (at subject-select.tsx:216)
in li (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (created by withRipple(Function))
in Ripple (created by class_1)
in class_1 (created by withRipple(Function))
in withRipple(Function) (at subject-select.tsx:211)
in ul (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at subject-select.tsx:161)
in div (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in PortalChild (created by Function)
in Function (at subject-select.tsx:155)
in div (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at subject-select.tsx:154)
in SubjectSelect (at covid-form.tsx:108)
in form (at covid-form.tsx:197)
in div (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at covid-form.tsx:184)
in Form (at covid-pupil-form.tsx:43)
in div (at covid-pupil-form.tsx:42)
in div (at covid-pupil-form.tsx:41)
in PupilForm (at pupils.tsx:12)
in PupilsPage (at _app.tsx:10)
in DBProvider (at _app.tsx:9)
in App
in Container (created by AppContainer)
in AppContainer
This needs to be addressed must likely by modifying the SubjectSelect
component definition in src/subject-select/lib/subject-select.tsx
such that the Checkbox
is always a "controlled component."
We want to remove the workaround specified in this issue for using the src/pages
directory as a Lerna package.
This is likely to be fixed by addressing #56.
The biggest concern in all nonprofits like this one is safeguarding. How are you going to run background checks on your volunteer tutors? How does one know if their tutor is qualified? Who is liable if something terrible happens between the volunteer tutor and the student that you connected?
Our recommended safeguarding flow looks like this:
Students must enter their parent’s contact info before sending lesson requests. Parents then receive emails for each lesson request with:
- The tutor’s profile (that the tutor inputs on our site)
- The tutor’s verified (via an academic email address) university position (e.g. “student at Duke University”)
- Links to the tutor’s (verified) social accounts (e.g. their LinkedIn, Facebook, Instagram)
An option to run (and pay for) various background checks (e.g. a state-wide sex-offender lookup or DBS check)
Note that once a background check has been paid for by one parent, that background check is added to the site and becomes available to everyone at no extra cost.
Once the parent signs off on a tutor, the student will meet with them via Bramble (no direct contact info is ever shared).
Parents are also encouraged to join the first tutoring session.
Right now (in @tutorbook/subject-select
), I'm using a this.state.inputValueWorkaround
field to ensure that the input value contains a non-breaking space (i.e. &nsbp;
or \xa0
) whenever there are subjects selected (i.e. when there are chips within the TextField
).
Workaround below (in src/subject-select/lib/subject-select.tsx
on line 87):
/**
* Workaround for styling the input as if it has content. If there are
* subjects selected (in the given `subjects` object), this will return a
* string containing a space (`' '`) so that the `TextField` styles itself as
* if it were filled.
* @todo Ideally, remove this workaround. But instead, make the `&nsbp;`
* actually show up as a non-breaking space (i.e. nothing).
* @see {@link https://github.com/jamesmfriedman/rmwc/issues/601}
* @return {string} The input value (either `' '` or `''`).
*/
getInputValue(
subjects: { [subject: string]: boolean } = this.state.subjects,
): string {
const selected = Object.values(subjects).reduce((a, b) => a || b, false);
return selected ? '\xa0' : '';
}
See this issue and this issue for more info on how I went about implementing our SubjectSelect
component.
We're using the Firebase Admin Node.js SDK on our serverless API functions (with Next.js) and have added the API key as a FIREBASE_ADMIN_KEY
environment variable but it seems to be formatted incorrectly on Vercel Now.
I just created an example of our issue:
To reproduce the error, open the logs for the /api/admin
serverless function on Vercel and invoke the function (i.e. by opening this link). You should see the following error from the Firebase Admin Node.js SDK:
2020-04-29T16:27:44.172Z 7d6a342a-b7ec-4b25-9eb0-136dab0c3c56 ERROR FirebaseAppError: Failed to parse private key: Error: Invalid PEM formatted message.
at FirebaseAppError.FirebaseError [as constructor] (/var/task/node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (/var/task/node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseAppError (/var/task/node_modules/firebase-admin/lib/utils/error.js:123:28)
at new ServiceAccount (/var/task/node_modules/firebase-admin/lib/auth/credential.js:142:19)
at new ServiceAccountCredential (/var/task/node_modules/firebase-admin/lib/auth/credential.js:68:15)
at Object.cert (/var/task/node_modules/firebase-admin/lib/firebase-namespace.js:219:58)
at Module.Wyqg (/var/task/.next/serverless/pages/api/admin.js:262:73)
at __webpack_require__ (/var/task/.next/serverless/pages/api/admin.js:23:31)
at Server.module.exports.HQqF.__webpack_exports__.default (/var/task/.next/serverless/pages/api/admin.js:194:28)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
errorInfo: {
code: 'app/invalid-credential',
message: 'Failed to parse private key: Error: Invalid PEM formatted message.'
},
codePrefix: 'app'
}
This is definitely an issue with Vercel’s environment variables, as it works fine in my development environment (i.e. running next dev
works fine).
See the Firebase docs for more info on how that's working.
From @kartik918's issue in the wrong repository:
We could implement a goal and reward-based system. A student can set a certain goal and if he reaches it within the time-limited he will receive a reward. The reward maybe some kind of medals that will be added to his profile description.
Similar implementation by Hackerrank for inspo:
The problem
Our existing availability input constrains the user to 3-hr blocks of time and can be rather time-consuming to check (or uncheck after a "Select all" click) each box.
The solution
We'll need an input that will:
I already pinged our design team on this, hopefully they'll have a solution designed that we can then implement soon.
hey guys, we need to add a grading to all the courses like for example, we could put 'senior/grade 12' instead of just senior. Like this students from diff countries can have a better understanding of the system.
We need to get rid of this error that shows up due to our ScheduleInput
every time our home page is loaded:
Warning: Prop `id` did not match. Server: "toggle--gxfg3t7xwo" Client: "toggle--ki0j10p2l"
in input (created by Function)
in div (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by ForwardRef(CheckboxRoot))
in ForwardRef(CheckboxRoot) (created by withRipple(Object))
in Ripple (created by class_1)
in class_1 (created by withRipple(Object))
in withRipple(Object) (created by Function)
in Function (at schedule-input.tsx:154)
in td (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at schedule-input.tsx:153)
in tr (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at schedule-input.tsx:139)
in tbody (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at schedule-input.tsx:136)
in table (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at schedule-input.tsx:127)
in div (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at schedule-input.tsx:126)
in div (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in PortalChild (created by Function)
in Function (at schedule-input.tsx:121)
in div (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at schedule-input.tsx:120)
in ScheduleInput (at covid-form.tsx:124)
in form (at covid-form.tsx:197)
in div (created by ForwardRef(Tag))
in ForwardRef(Tag) (created by Function)
in Function (at covid-form.tsx:184)
in Form (at hero-form.tsx:24)
in div (at hero-form.tsx:23)
in div (at hero-form.tsx:22)
in HeroForm (at pages/index.tsx:13)
in IndexPage (at _app.tsx:10)
in DBProvider (at _app.tsx:9)
in App
in Container (created by AppContainer)
in AppContainer
See this issue for more info.
We need to add the lang
tag to the top-level <html>
tag via a custom Next.js Document
like so:
<html lang="en">
This is going to be rather difficult to do however, as we do not want to give up SSG and SSR but we want to have a different lang
tag for each different locale (i.e. the locales that are used to SSG src/pages/[locale]/*
).
When searching for a tutor, some of the results returned doesn't match availability of student and tutor
We need to add the following to each of the pages in src/pages/
:
<title>
tag).Follow these instructions on how to use the built-in Next.js Head
object.
We want to remove any dependencies on the Firebase JavaScript SDK from our client-side bundle. That SDK is pretty big (I think it's taking up the bulk of our bundle right now) and we're only using it for Authentication and Google Analytics.
Ideally, we'll want to implement something similar to what is described here to intercept requests to the api/
endpoints and add a token
parameter or an Authentication
HTTP header (containing our Firebase Authentication idToken
which is used by our API endpoints to authenticate our requests via the Firebase Admin Node.js SDK).
Right now, our Firebase Authentication is implemented in src/firebase/lib/
primarily in src/firebase/lib/user.ts
. We use React Context
to make the current User
object accessible to everything in the React tree (see src/pages/_app.tsx
where we add a UserProvider
to the top of the Next.js app).
I thought this would be easy, but it turns out that Google doesn't have a maintained implementation of their Material Design Guidelines for React. They used to but it's no longer maintained.
There are many third-party implementations though:
And probably many more that aren't even maintained enough to be listed here as viable options. After reading a bunch of blog posts (listed below), I'm thinking I'm going to go with RMWC instead of the ever-more-popular Material UI:
Our SubjectSelect
React component (defined in src/subject-select
) takes the current input and uses it to search all the possible subject that then appear in the drop-down select menu (see below).
The problem with this, however, is that once the user selects a subject from that select menu, the current search input is cleared but the search results (i.e. the subjects listed in that select menu) stay the same (see below).
The most intuitive fix here (in my opinion), is to just keep their search input full even after they select a subject from the drop-down select menu. We'll just force them to clear it when they want to see the original subject list again.
Current workaround in src/subject-select/lib/subject-select.module.scss
:
@use '@material/chips/_index.scss' as chips;
We want it to read like (this should automatically import _index.scss
and create a chips
namespace):
@use '@material/chips'
See this original issue for more info.
From @AlephTaw's original issue:
Version 2 Google Slides - Feel free to insert revisions, so we can collab/compare/keep a tight product to UI/UX feedback loop.Thanks!!!
Pages:
Landing Page:
Parents, Students <-> Tutors
Nav Bar: About, Meet our Team!, Contact, Volunteer, FAQs, Student Resources
Student Page:
Layout: Side-by-side - Description | Form
LogIn or signup - Description of the service … Here’s how we can help you get individualized educational support during the covid -19 … 1) Sign Up 2) … 3) One of our tutors.
Student Sign-Up:
Parent, Student:
Want to learn more about us? Meet our team, visit our FAQs, or contact us.
Fills out Form (Below):
Parent Name*
Parent Phone Number*
Parent Email*
Student Name*
Student Email*
Grade Level
City
State
ZipStudent Login:
-> Student Account: Tutor Portfoliio -> Grid of (Tutors, Subjects) Pairs w/ mini Bios and next appointment (time, day, date in student time zone), a link to their Google Drive Folder (and subfolders (one for each tutor)), ability to submit a rating: 1-5 stars + text field to submit reviews, I would like to report an issue (checkbox), to tutor records [submit], button for canceling an appointment (3 Drop Maximum: If you are having trouble matching with a tutor, contact us.)Make an Appointment:
Subject
Grade Level
Weekly Availability (To maximize your options, include all times that you can make on a weekly basis):Student Resources:
A collection of well formatted links with descriptions - scour
from other sites, etc.Tutor Page:
Login or Signup to Volunteer
Sign Up:
Email*
Name*
Phone Number*
Which of the following have you attained:* In college, college, Masters, PhD
Do you have experience tutoring professionally:
Yes
NoNumber of Years:* 1, 2, 3, 4, 5, +
School [Text Field]
City:
State:
Zip:Hobbies:
Hobby 1:
Hobby 2:
Hobby 3:Message (tutors can add their comments) [text field]:
#Notes: Tutor bios will be automatically generated as: “Hi, my name is NAME. I am currently getting/have completed my degree in DEGREE. I am volunteering with covidtutoring.org to help students everywhere regain educational access! In my free time I enjoy ___, ____, and _./ and /
Once Logged In -->
Student Roster: Grid view (Student: First Name ?, subject, next appointment)
Calendar where tutors can block off their weekly commitments (on the half hour in their local time zones).
FAQs:
What is CovidTuotoring.org / Tutorbook … or whatever.
How you we are able to offer free support
How we ensure a quality experience
General Guidelines for Protecting your privacy online
How you are in control when using our product
How we are helping our communities
I've heard from two people so far on the current behavior of our SubjectSelect
component (see #17 for some more info on the first person's perspective).
I've come up with two possible behaviors for the SubjectSelect
that are listed below:
input
field and reset the select menu when a subject is selected.input
field content and the select menu state when a subject is selected (i.e. do nothing).Right now, we're running on behavior two so that users can easily select multiple subjects in the same area (e.g. type in "Chem" and select "Chemistry H", "Chemistry", "SAT Chemistry", and "AP Chemistry" without having to re-type in "Chem").
The solution for this issue should be to run some type of A/B testing or survey to see which is actually more popular.
The ultimate goal for our SubjectSelect
component is to replicate Gmail's compose to
field (as pictured below):
It seems that Gmail uses some type of JavaScript to manually resize (set the width
) of the textarea
in that input element every time a new recipient is added (i.e. when a Chip
is added). We, however, just put the textarea
on a new line (using flex-wrap: wrap;
). See picture below:
It'd be nice to have that textarea
stay on the line as the Chip
s for as long as possible (i.e. until it becomes less than, say, 10px
).
Right now, the @tutorbook/covid-form
only supports Select
's that use the options
prop to add options to the mdc-list
within the mdc-menu
. We want to be able to support customizing and manually building those options
as detailed here (under "Manually building the list") such that we can add mdc-list-divider
s in between item grouping.
We still need to find a workaround for @use
-ing @material
's Sass modules as detailed in this issue.
This is probably much too large to be a single GitHub issue, but I'm going to create it here if not just for the sake of consistency.
Acceptance tests
These are UI/UX tests that emulate what a user would do to ensure that the final product is fully functional. We'll probably use Cypress or the Robot Framework for these.
We'll probably also run our Google Lighthouse tests along with these UI tests (see "performance tests" for more info).
These tests will be run after every commit via Travis-CI or GitHub Actions. It will also be run automatically for every new PR.
Unit tests
There are unit tests of each class, their methods, functions, etc. These should be as small as possible and will probably be implemented using Jest, React tree snapshots, Enzyme, and similar unit testing tools.
Performance tests
Essentially, setup Travis-CI or GitHub Actions tasks to automatically run our build (without deploying anything) so that we can see how our bundle sizes change.
For PRs and other commits that are deployed by Vercel for previewing, we'll want to run Google Lighthouse tests (right now, we've got it setup with this Vercel integration but we want it to show up on GitHub).
In the future, we'll also probably want to benchmark our acceptance tests (e.g. how much are we using the CPU, how much RAM are we using, etc). But for now, I think that tracking bundle size is our main priority.
Some feedback (from my sister and from @Simk-ops):
The subject select is a tad bit confusing b/c all the subjects available aren't in the list and it isn't intuitive to search by typing.
And I think you sister is right, the subject select is a little confusing. I feel like we can add more specifications like Algebra, Pre-Algebra, Calculus, Linear, etc. What are yout thought on this?
To address this:
We want to automatically generate our documentation after every git push
(likely using GitHub Actions or our Travis-CI) that parses:
We'll probably want to use something like react-docgen
paired with Docusaurus. Ideally, the styling of the docs should match the styling of our website or Tutorbook's existing documentation that is generated with our @tutorbook/minami
theme.
We want our Select
components to auto-select based on user input (this is already pretty common for most native browser <select>
tags, but isn't yet officially supported by the MDC Select component). When the Select
is focused, we should listen for keydown
events and select the options that match the typed letters.
Perhaps this is beyond the scope of this repository however, and should instead be created as an issue in the @rmwc/select
repository.
I've already implemented this for Tutorbook's web app. That implementation from src/app/packages/utils/index.js
is included below:
/**
* Attaches the given select by:
* 1. Populating it's options with the options in the `mdc-list`.
* 2. Listening for `keydown` events that act as shortcuts to select an
* option (like most native `select` elements do).
* @param {HTMLElement} selectEl - The `mdc-select` element to attach.
* @return {external:MDCSelect} The attached `MDCSelect` instance.
*/
static attachSelect(selectEl) {
// Initialize select
if (typeof selectEl === 'string') selectEl = $(selectEl)[0];
const ops = [];
$(selectEl).find('.mdc-list-item').each(function() {
MDCRipple.attachTo(this);
if (ops.indexOf(this.innerText) < 0) ops.push(this.innerText);
});
const selected = $(selectEl).find('.mdc-select__selected-text').text();
const select = MDCSelect.attachTo(selectEl);
// Helper functions
const lastClicked = []; // Last inputted shortcut keys
const selectOption = (op) => select.selectedIndex = ops.indexOf(op);
const listen = (event) => {
const justClicked = event.keyCode;
const possible = ops.filter(option => {
option = option.toUpperCase();
var i = 0;
for (i; i < lastClicked.length; i++)
if (option.charCodeAt(i) !== lastClicked[i])
return false;
return option.charCodeAt(i) === justClicked;
});
if (possible.length === 1) {
lastClicked.length = 0;
selectOption(possible[0]);
} else if (possible.length > 1) {
lastClicked.push(justClicked);
}
};
// Render empty selects even when val is null, undefined, or false
if (selected !== '') selectOption(selected);
// Listen for shortcut keys (when select is in focus)
$(selectEl).on('focusin', () => $(document).keydown(listen));
$(selectEl).on('focusout', () => $(document).off('keydown', listen));
return select;
}
We've decided to use React with Typescript for this project for a couple of reasons:
jsdoc
with @tutorbook/minami
to automatically generate our documentation from our source code after every git commit
).Right now, we're just catching and logging error messages but we aren't actually showing anything to the client (so they think that their request succeeded if they don't open up a console and look at the logs) in:
PupilForm
in src/pupil-form/lib/covid-pupil-form.tsx
that calls /api/user
TutorForm
in src/tutor-form/lib/covid-tutor-form.tsx
that calls /api/user
HeroForm
in src/hero-form/lib/hero-form.tsx
that calls /api/user
SearchResults
in src/search/lib/results.tsx
that calls /api/search
UserDialog
in src/user-dialog/lib/user-dialog.tsx
that calls /api/appt
We need to show some type of pop-up dialog explaining what went wrong with each error code and how they can address it (such a dialog should also include a CTA button to open our Intercom messenger and chat with support).
We want to update the footer on our website using the styling from the old website's footer so that it looks a little like:
It should include links to the following pages (most of which have yet to be built, but it should be pretty straight forward to create them):
mailto:[email protected]
link)In the future, it should also include links to the last couple of blog posts (once we get that setup using Ghost).
Read the Next.js documentation on custom error pages and implement our own custom error page using the styling from the rest of the site (e.g. use @rmwc/typography
, perhaps a nice background image from our web assets, etc).
Note that this error page should have as little text as possible (because it has to be static and thus we can't use react-intl
for i18n). Or just include the error message in all of our supported locales (see the list in src/intl/config.json
).
Right now, our Timeslot
strings look something like this:
Mondays 12:00:00 PM - 1:00:00 PM
7:00:00 AM - 12:00:00 PM
Or, even worse in the TimeslotInput
within our UserDialog
, it looks like this:
Mondays 12:00:00 AM - 17:00:00 AM
We need to make those strings more human readable (e.g. Mondays 12 - 1 PM
or 7 AM - 12 PM
).
And for the ScheduleInput
we'll want to make them secondary to the time of day (e.g. Mornings (7 AM - 12 PM)
instead of 7:00:00 AM - 12:00:00 PM
).
Right now, the UserDialog
displays plain text links for the user's social media accounts like so:
Ideally, we want them to be easily recognizable yet still discreet social media icons (probably all in gray and pretty small).
Consult with our design team (e.g. @kryssym) to review your work once you're finished.
We want to be as global as possible which means supporting as many locales as we can find translators for. We need to de-couple the the translation text from our code (i.e. static content should be moved away from the codebase).
I've researched some options for different i18n libraries but they all seem to have their own setbacks:
next-i18next
server.js
which we do not want to do (we won't be able to statically pre-render anything).react-intl
next-i18next
).i18next
react-i18next
For now, I'm going to keep using react-intl
until I come up against any blocking issues. Note that react-intl
also has a Slack workspace which will be good for support concerns, etc.
See comments in src/model/lib/times.ts
for more info:
1 import * as firebase from 'firebase';
2 import 'firebase/firestore';
3
4 /**
5 * This is a painful workaround as we then import the entire Firebase library
6 * definition while we only want the `Timestamp` object.
7 * @todo Only import the `Timestamp` definition.
8 * @see {@link https://stackoverflow.com/a/57984831/10023158}
9 */
10 const Timestamp = firebase.firestore.Timestamp;
11 type Timestamp = firebase.firestore.Timestamp;
We only want to import
the Timestamp
object (as defined here), not all of Firebase just to access that one class.
Also, that import on the server-side of things seems to produce a Firebase warning log (which we definitely don't want):
It looks like you're using the development build of the Firebase JS SDK.
When deploying Firebase apps to production, it is advisable to only import
the individual SDK components you intend to use.
For the module builds, these are available in the following manner
(replace <PACKAGE> with the name of a component - i.e. auth, database, etc):
CommonJS Modules:
const firebase = require('firebase/app');
require('firebase/<PACKAGE>');
ES Modules:
import firebase from 'firebase/app';
import 'firebase/<PACKAGE>';
Typescript:
import * as firebase from 'firebase/app';
import 'firebase/<PACKAGE>';
Super easy fix (I'll probably do this one later in just a second), but we want to rename the parent
property on the User
and UserInterface
to be parents
instead (as it's an array of the user's parents's uIDs).
no need to repeat math grade1 math grade 2 etc each timeIt will be way easier if when the students select his grade, the system show hi all the subjects which are available. like no need to show him all the subjects from grade1 to 8.
Have an image background carousel with messages geared towards each type of user (Students, teachers and parents). It will give visitors a general idea of the service upon landing.
The problem
Right now, if an /api/
request fails, we still show the checkmark and the client thinks that the request succeeded (unless, for some strange reason, they think to open up the console and look at the error logs).
The solution
Actually implement the /api/
endpoint requirements that are outlined here:
Each of these API functions catches all known errors and sends them back to the client in plain English (i.e. you can display res.data to the user when you receive a 400 or 500 HTTP error code).
Then, just display the error codes that are sent back by our API endpoints.
Note that you should consult with design on how to best show those error codes (as that's very much a front-end job).
Right now, our SubjectSelect
consists of a TextField
(with the textarea
property set to true
) that contains a ChipSet
with Chips
for each currently selected subject.
There are many problems with this setup though (another detailed in #8) one being that the MenuSurface
doesn't move when the TextField
expands:
We have to somehow update the location state on that MenuSurface
whenever the TextField
expands such that the menu is always anchored to the start of the bottom of the TextField
component.
Debug why the label isn't floating on the grade level Select
in the PupilForm
(defined in src/pupil-form/lib/covid-pupil-form.tsx
).
You can view the error (pictured below) by going to the pupil's page and filling out the "Your grade level" field.
Current nav bar has a link to our repo from the landing page Nav.
We should remove it till the time our repository is private since an outside developer can't see it till the project is public.
Right now, whenever we create a TextField
to collect phone numbers, we make sure to set the input
type to tel
. But I don't think that the browser-native tel
validation/verification is that great, so this issue aims to make it better by:
RegExp
or similar to ensure that the phone number looks right.+1
which is the United States' phone extension).phone
package to help out.Describe the bug
A clear and concise description of what the bug is.
We catch the auth/email-already-exists
and auth/phone-number-already-exists
Firebase Authentication errors when creating the pupil and tutor accounts but not when creating parent accounts.
To Reproduce
Steps to reproduce the behavior:
Proposed fix
A clear and concise description of what you expected to happen.
We should bring the error catching that is already implemented for tutor and pupil account creation into a higher-order function that we'll call to create parent accounts as well (i.e. we'll catch all of the account creation errors in that function).
See src/pages/api/user.ts
for more info.
When volunteers fill out the tutoring application, there can be a slot to pick a cancellation time period. For example
If Tutor A's Cancellation time period is : 3hrs then the student must cancel at least 3 hrs before the session if they wish to.
The problem
Our existing timeslot input is rather painful (i.e. as a user you have to read the helper text carefully to see what timeslots are available for selection) and is text-based (which makes i18n hard and forces the user to type out "Mondays from 3:00 PM to 3:30 PM").
The solution
Just posted to the #team-design Slack channel with this, so hopefully we'll have a solution designed soon:
Hey @channel could you help design a timeslot input that will:
- Replace the text-based one in the UserDialog (see above picture).
- Select a timeslot (e.g. "Mondays from 3:00 PM to 3:30 PM") from a given availability.
We want to be able to call:
import Router from 'next/router';
Router.push('/search');
And then automatically be sent to the locale-specific page (i.e. /search
goes to /en/search
without a redirect to /api/redirect
).
I tried implementing this in src/intl/lib/router.ts
but gave up after a while (you should find some useful links there to get you started on this):
import NextRouter from 'next/router';
import { IntlCache, IntlShape, createIntl, createIntlCache } from 'react-intl';
import { UrlObject } from 'url';
type Url = UrlObject | string;
/**
* Adds the locale to the given url string or object.
* @see {@link https://github.com/isaachinman/next-i18next/blob/master/src/utils/lng-path-corrector.ts}
* @see {@link https://github.com/isaachinman/next-i18next/blob/master/src/router/wrap-router.ts}
*/
function addLocale(url?: Url): Url | undefined {
const cache: IntlCache = createIntlCache();
const intl: IntlShape = createIntl(
{
locale: 'TODO: Somehow grab locale from outside the React lifecycle.',
},
cache
);
if (typeof url === 'string') {
url = `/${intl.locale}${url}`.replace(/\/$/, '');
} else if (typeof url === 'object') {
url.pathname = `/${intl.locale}${url.pathname}`.replace(/\/$/, '');
}
return url;
}
export class Router extends NextRouter {
push(url: Url, as?: Url, options?: {}): Promise<boolean> {
return super.push(addLocale(url), addLocale(as), options);
}
replace(url: Url, as?: Url, options?: {}): Promise<boolean> {
return super.replace(addLocale(url), addLocale(as), options);
}
}
Is your feature request related to a problem? Please describe.
In the "Education and Experience" field, the new lines that you enter should be preserved. For example, a user might enter the following:
- Bachelors (Hons)
- Maths Masters (Hons)
- Applied Mathematics Professional
- Risk Analyst (8 months experience) Professional Experience
- Senior Subject Matter Expert
- Mathematics (present)
But then their profile shows up in the UserDialog
without any of the newlines:
Describe the solution you'd like
We should:
textarea
s.While we use Google's NoSQL Firestore database for data storage, it's built-in querying capabilities are far from what we need to be able to do for our search MVP (e.g. it's incredibly difficult to search by text, synonyms, or custom Date
-like objects).
We should sync our database with Algolia using GCP Cloud Functions that trigger after every document change. Then, we'll use Algolia's client-side SDK to query and filter that data, gradually exposing more filter parameters to the end user.
For our MVP, we'll need to be able to filter by:
subjects.explicit
field contains Chemistry H
).availability
field contains a Timeslot
whose open time is equal to or before the desired open time and whose close time is equal to or after the desired close time).Eventually, it might be nice to filter by:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.