├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ ├── ---feature-request---.md
│ └── bug_report.md
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── archive
└── pages
│ └── hackrplay
│ └── 2022
│ └── registration
│ ├── [id].js
│ └── index.js
├── components
├── Buttons.js
├── Footer.js
├── Hack-R-Play
│ ├── IdeaFilter.js
│ └── index.js
├── Header.js
├── Ideas
│ └── Card.js
├── Layout.js
├── LayoutWrapper.js
├── LinkLabel.js
├── OwnerFilter.js
├── Pagination.js
├── SortButtons.js
├── StatusFilter.js
├── common
│ ├── About.js
│ ├── CTA.js
│ ├── ChallengesAndPrizes.js
│ ├── FAQs.js
│ ├── Hero.js
│ ├── Judges.js
│ ├── Partners.js
│ ├── Winners.js
│ └── index.js
├── form-builder
│ └── index.js
├── interactions
│ └── index.js
└── status-bar
│ └── StatusBar.js
├── jsconfig.json
├── next.config.js
├── package-lock.json
├── package.json
├── pages
├── _app.js
├── api
│ └── hello.js
├── events
│ ├── 22
│ │ └── hackrplay
│ │ │ ├── ideas
│ │ │ ├── [id].js
│ │ │ ├── index.js
│ │ │ └── submit
│ │ │ │ └── [id].js
│ │ │ └── index.js
│ └── 23
│ │ └── twoplaysamonth
│ │ └── index.js
├── index.js
└── tech-credit.js
├── postcss.config.js
├── public
├── 2plays-a-month
│ └── og-image-twoplaysamonth.png
├── FooterReactLogo.svg
├── FooterTriangles.svg
├── Idea-List
│ ├── completed.svg
│ ├── inProgress.svg
│ └── notStart.svg
├── Logo.png
├── Nextjs-logo.png
├── ReactPlayLogo.svg
├── common
│ ├── DottedAndFilledTriangle.svg
│ ├── DottedPattern.svg
│ ├── Flower.svg
│ ├── GradientAndSmallTriangle.svg
│ ├── HeroLines.svg
│ ├── Lines.svg
│ ├── RadialGradient.svg
│ └── ReactPlayLogoDotted.svg
├── favicon.png
├── hackrplay
│ ├── BannerLogo.png
│ ├── CTAImage.svg
│ ├── GradientAndSmallTriangle.svg
│ ├── GradientFlower.svg
│ ├── HeroCoders.svg
│ ├── NavbarLogo.png
│ ├── NhostLogo.svg
│ ├── PartnersPolygon.svg
│ ├── ReactPlayLogoDotted.svg
│ ├── og-image.png
│ └── partner0.png
├── robots.txt
├── tailwindcss-logotype.svg
└── twoplaysamonth
│ ├── BannerLogo.png
│ ├── CTAImage.svg
│ ├── GradientAndSmallTriangle.svg
│ ├── GradientFlower.svg
│ ├── HeroCoders.svg
│ ├── NavbarLogo.png
│ ├── PartnersPolygon.svg
│ ├── ReactPlayLogoDotted.svg
│ ├── og-image.png
│ ├── partner0.png
│ └── partner0.svg
├── services
├── consts
│ ├── registration-fields.js
│ ├── registration-update-fields.js
│ ├── submission-fields.js
│ └── theme.js
├── graphql
│ ├── auth.js
│ ├── ideas.js
│ ├── interactions.js
│ └── status.js
├── metadata
│ ├── hackrplay.js
│ ├── index.js
│ └── twoplaysamonth.js
├── nhost
│ └── index.js
├── request
│ └── index.js
└── util
│ ├── string.js
│ └── time.js
├── styles
├── Common-component.module.css
├── Home.module.css
├── form-control.css
├── globals.css
└── idea.module.css
└── tailwind.config.js
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [reactplay]
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/---feature-request---.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "✨ [Feature request]: "
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | /node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # next.js
37 | /.next/
38 | /out/
39 | # production
40 | /build
41 |
42 |
43 | # Optional REPL history
44 | .node_repl_history
45 |
46 | # local env files
47 | .env*.local
48 | .env
49 |
50 | # DS Store
51 | .DS_STORE
52 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | ioreactplay@gmail.com.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via [issue](https://github.com/reactplay/activities/issues),
4 | [email](mailto:contact@reactplay.io), or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a [Code of Conduct](https://github.com/reactplay/activities/blob/main/CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
7 |
8 | ## Pull Request Process
9 |
10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a
11 | build.
12 | 2. Update the README.md with details of changes to the interface, this includes new environment
13 | variables, exposed ports, useful file locations and container parameters.
14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this
15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
17 | do not have permission to do that, you may request the second reviewer to merge it for you.
18 |
19 | ## Code of Conduct
20 |
21 | ### Our Pledge
22 |
23 | In the interest of fostering an open and welcoming environment, we as
24 | contributors and maintainers pledge to making participation in our project and
25 | our community a harassment-free experience for everyone, regardless of age, body
26 | size, disability, ethnicity, gender identity and expression, level of experience,
27 | nationality, personal appearance, race, religion, or sexual identity and
28 | orientation.
29 |
30 | ### Our Standards
31 |
32 | Examples of behavior that contributes to creating a positive environment
33 | include:
34 |
35 | * Using welcoming and inclusive language
36 | * Being respectful of differing viewpoints and experiences
37 | * Gracefully accepting constructive criticism
38 | * Focusing on what is best for the community
39 | * Showing empathy towards other community members
40 |
41 | Examples of unacceptable behavior by participants include:
42 |
43 | * The use of sexualized language or imagery and unwelcome sexual attention or
44 | advances
45 | * Trolling, insulting/derogatory comments, and personal or political attacks
46 | * Public or private harassment
47 | * Publishing others' private information, such as a physical or electronic
48 | address, without explicit permission
49 | * Other conduct which could reasonably be considered inappropriate in a
50 | professional setting
51 |
52 | ### Our Responsibilities
53 |
54 | Project maintainers are responsible for clarifying the standards of acceptable
55 | behavior and are expected to take appropriate and fair corrective action in
56 | response to any instances of unacceptable behavior.
57 |
58 | Project maintainers have the right and responsibility to remove, edit, or
59 | reject comments, commits, code, wiki edits, issues, and other contributions
60 | that are not aligned to this Code of Conduct, or to ban temporarily or
61 | permanently any contributor for other behaviors that they deem inappropriate,
62 | threatening, offensive, or harmful.
63 |
64 | ### Scope
65 |
66 | This Code of Conduct applies both within project spaces and in public spaces
67 | when an individual is representing the project or its community. Examples of
68 | representing a project or community include using an official project e-mail
69 | address, posting via an official social media account, or acting as an appointed
70 | representative at an online or offline event. Representation of a project may be
71 | further defined and clarified by project maintainers.
72 |
73 | ### Enforcement
74 |
75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
76 | reported by contacting the project team at [contact@reactplay.io](mailto:contact@reactplay.io). All
77 | complaints will be reviewed and investigated and will result in a response that
78 | is deemed necessary and appropriate to the circumstances. The project team is
79 | obligated to maintain confidentiality with regard to the reporter of an incident.
80 | Further details of specific enforcement policies may be posted separately.
81 |
82 | Project maintainers who do not follow or enforce the Code of Conduct in good
83 | faith may face temporary or permanent repercussions as determined by other
84 | members of the project's leadership.
85 |
86 | ### Attribution
87 |
88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
89 | available at [http://contributor-covenant.org/version/1/4][version]
90 |
91 | [homepage]: http://contributor-covenant.org
92 | [version]: http://contributor-covenant.org/version/1/4/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 ReactPlayIO
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Activities
2 | A `reactplay` hustle
3 |
4 | This is a [Next.js](https://nextjs.org/) project.
5 |
6 | ## Getting Started
7 |
8 | 1. Install dependencies
9 | ```bash
10 | yarn
11 | ```
12 | **Note**: We do check in yarn.lock file. So it's advised to use `yarn` package manager. If you need to use any other package manager, remove `yarn.lock` file from the local directory first. Also, do not check in any other lock file.
13 | 2. Create a `.env` file at the root of your project folder with the following content,
14 |
15 | ```bash
16 | NEXT_PUBLIC_NHOST_BACKEND_URL=https://rgkjmwftqtbpayoyolwh.nhost.run
17 | NEXT_PUBLIC_NHOST_SUBDOMAIN=rgkjmwftqtbpayoyolwh
18 | NEXT_PUBLIC_NHOST_REGION=ap-southeast-1
19 | NEXT_PUBLIC_NHOST_PROTOCOL=https
20 | NEXT_PUBLIC_NHOST_SERVER=rgkjmwftqtbpayoyolwh.nhost.run
21 | NEXT_PUBLIC_NHOST_VERSION=v1
22 | NEXT_PUBLIC_NHOST_ENDPOINT=graphql
23 | NEXT_PUBLIC_DEV_PORT=3000
24 | NEXT_PUBLIC_PROTOCOL=http
25 | NEXT_PUBLIC_HACKATHON_ID=e606ae64-7c92-4344-94ad-4d0684458bcf
26 | NEXT_PUBLIC_HACKATHON_SUBMIT_STATUS_ID=ec1c0649-3b65-4809-92cf-9c4a6abdff1b
27 | ```
28 | 3. Run the development server:
29 |
30 | ```bash
31 | npm run dev
32 | # or
33 | yarn dev
34 | ```
35 |
36 | 4. See your application running
37 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
38 |
--------------------------------------------------------------------------------
/archive/pages/hackrplay/2022/registration/[id].js:
--------------------------------------------------------------------------------
1 | import { useAuthenticationStatus, useUserData } from '@nhost/nextjs';
2 | import styles from '@/styles/Home.module.css';
3 |
4 | import { FiCheckCircle } from 'react-icons/fi';
5 | import { NHOST } from '@/services/nhost';
6 | import { useEffect, useState, forwardRef } from 'react';
7 | import FormBuilder from '@/components/form-builder';
8 | import { FIELD_TEMPLATE } from '@/services/consts/registration-update-fields';
9 | import { getAllUsers } from '@/services/graphql/auth';
10 | import {
11 | assign_member,
12 | get_idea,
13 | insert_idea,
14 | update_ideas_demographic,
15 | update_ideas_member,
16 | } from '@/services/graphql/ideas';
17 | import {
18 | PrimaryButton,
19 | SecondaryOutlinedButtonDark,
20 | } from '@/components/Buttons';
21 | import { useRouter } from 'next/router';
22 | import LayoutWrapper from '@/components/LayoutWrapper';
23 | import Snackbar from '@mui/material/Snackbar';
24 | import MuiAlert from '@mui/material/Alert';
25 | import { submit } from 'json-graphql-parser/v2';
26 | import {
27 | get_latest_status,
28 | insert_ideas_status,
29 | list_statuses,
30 | update_ideas_status,
31 | } from '@/services/graphql/status';
32 | import { escape_new_line, unescape_new_line } from '@/services/util/string';
33 |
34 | const Alert = forwardRef(function Alert(props, ref) {
35 | return ;
36 | });
37 |
38 | export default function RegistrationEdit() {
39 | const { isAuthenticated, isLoading } = useAuthenticationStatus();
40 | const [isDataLoading, setIsDataLoading] = useState(true);
41 | const [isSubmitting, setIsSubmitting] = useState(false);
42 | const [storedIdeaData, setStoredIdeaData] = useState({});
43 | const [formData, setFormData] = useState({});
44 | const [alertOpen, setAlertOpen] = useState(false);
45 | const [pageDisabled, setPageDisabled] = useState(false);
46 |
47 | const userData = useUserData();
48 | const router = useRouter();
49 | const { id } = router.query;
50 |
51 | const initializeData = () => {
52 | if (Object.keys(storedIdeaData).length === 0) {
53 | setIsDataLoading(true);
54 | const all_apis = [
55 | { name: 'users', method: getAllUsers },
56 | {
57 | name: 'status',
58 | method: list_statuses,
59 | post_method: remove_submitted_status,
60 | },
61 | ];
62 | const promises = [];
63 |
64 | all_apis.forEach((api) => {
65 | promises.push(api.method());
66 | });
67 |
68 | promises.push(
69 | get_idea(id).then((r) => {
70 | const status = get_latest_status(r);
71 | r.description = unescape_new_line(r.description);
72 | if (
73 | status &&
74 | status.id ===
75 | process.env.NEXT_PUBLIC_HACKATHON_SUBMIT_STATUS_ID
76 | ) {
77 | router.push('../ideas');
78 | } else {
79 | prepare_idea_object(r);
80 | }
81 | })
82 | );
83 | Promise.all(promises)
84 | .then((res) => {
85 | res.forEach((rApi, rApi_ind) => {
86 | try {
87 | const api_obj = all_apis[rApi_ind];
88 | storedIdeaData[api_obj.name] = rApi;
89 | const anyField = FIELD_TEMPLATE.filter((field) => {
90 | return field.datafield === api_obj.name;
91 | });
92 | if (anyField.length) {
93 | anyField[0].options = api_obj.post_method
94 | ? api_obj.post_method(rApi)
95 | : rApi;
96 | }
97 | } catch (err) {
98 | // IGNORE
99 | }
100 | });
101 |
102 | setStoredIdeaData({ ...storedIdeaData });
103 | })
104 | .finally(() => {
105 | setIsDataLoading(false);
106 | });
107 | }
108 | };
109 |
110 | const remove_submitted_status = (all_statuses) => {
111 | return all_statuses.filter(
112 | (s) => s.id !== process.env.NEXT_PUBLIC_HACKATHON_SUBMIT_STATUS_ID
113 | );
114 | };
115 |
116 | const prepare_idea_object = (idea) => {
117 | if (idea.idea_members_map) {
118 | idea.users = idea.idea_members_map.user_id_map.id;
119 | }
120 | if (idea.idea_idea_status_map) {
121 | idea.status = get_latest_status(idea);
122 | const all_statuses = [];
123 |
124 | idea.idea_idea_status_map.forEach((st) => {
125 | all_statuses.push(st.idea_status_status_map);
126 | });
127 | const last_status = all_statuses[all_statuses.length - 1];
128 | idea.status = last_status?.id;
129 | }
130 | if (userData.id !== idea.idea_owner_map.id) {
131 | setAlertOpen(true);
132 | setPageDisabled(true);
133 | }
134 | setFormData({ ...idea });
135 | setStoredIdeaData({ ...idea });
136 | };
137 |
138 | useEffect(() => {
139 | if (!isLoading) {
140 | if (!isAuthenticated) {
141 | if (typeof window !== 'undefined') {
142 | const protocol = process.env.NEXT_PUBLIC_PROTOCOL
143 | ? process.env.NEXT_PUBLIC_PROTOCOL
144 | : 'https';
145 | const host = window.location.hostname;
146 | const port = process.env.NEXT_PUBLIC_DEV_PORT
147 | ? `:${process.env.NEXT_PUBLIC_DEV_PORT}`
148 | : '';
149 | const external_path = NHOST.AUTH_URL(
150 | `${protocol}://${host}${port}/registration`
151 | );
152 | window.location = external_path;
153 | }
154 | } else {
155 | initializeData();
156 | }
157 | }
158 | }, [isLoading]);
159 |
160 | if (isLoading) {
161 | return (
162 |
163 |
164 |
165 | Loading authentication information. Please wait.
166 |
167 |
168 |
169 | );
170 | }
171 |
172 | if (isDataLoading) {
173 | return (
174 |
175 |
176 |
177 | Checking authentication status. Please wait.
178 |
179 |
180 |
181 | );
182 | }
183 |
184 | const isFieldsAreInValid = () => {
185 | let res = false;
186 | FIELD_TEMPLATE.forEach((tmpl) => {
187 | if (tmpl.required && (!formData || !formData[tmpl.datafield])) {
188 | res = true;
189 | }
190 | });
191 | return res;
192 | };
193 |
194 | const onIdeaDataChanged = (data) => {
195 | setFormData({ ...data });
196 | setStoredIdeaData({ ...data });
197 | };
198 |
199 | const onSubmit = () => {
200 | setIsSubmitting(true);
201 |
202 | const idea_object = (({ title, description }) => ({
203 | title,
204 | description,
205 | }))(storedIdeaData);
206 | idea_object.owner = userData.id;
207 | formData.description = idea_object.description = escape_new_line(
208 | idea_object.description
209 | );
210 | const promises = [];
211 |
212 | promises.push(update_ideas_demographic(formData));
213 | promises.push(update_ideas_member(formData));
214 | if (formData.status) {
215 | promises.push(insert_ideas_status(formData));
216 | }
217 |
218 | Promise.all(promises).then((res) => {
219 | router.push('../ideas');
220 | });
221 | };
222 |
223 | const onCancelClicked = () => {
224 | router.push('../ideas');
225 | };
226 |
227 | return (
228 |
229 |
230 |
231 |
232 |
233 |
235 | Registration
236 |
237 |
238 |
239 |
240 | {' '}
241 | {alertOpen ? (
242 |
243 | You cannot edit this idea. Only author
244 | can edit an idea.
245 |
246 | ) : null}
247 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
265 | onCancelClicked()
266 | }>
267 | Cancel
268 |
269 |
270 |
271 |
272 |
onSubmit()}
278 | onClick={() => os()}>
279 | Update Idea
280 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 | );
294 | }
295 |
--------------------------------------------------------------------------------
/archive/pages/hackrplay/2022/registration/index.js:
--------------------------------------------------------------------------------
1 | import { useAuthenticationStatus, useUserData } from '@nhost/nextjs';
2 | import styles from '@/styles/Home.module.css';
3 |
4 | import Link from 'next/link';
5 | import { FiCheckCircle } from 'react-icons/fi';
6 | import { NHOST } from '@/services/nhost';
7 | import { useEffect, useState } from 'react';
8 | import FormBuilder from '@/components/form-builder';
9 | import { FIELD_TEMPLATE } from '@/services/consts/registration-fields';
10 | import { getAllUsers } from '@/services/graphql/auth';
11 | import { assign_member, insert_idea } from '@/services/graphql/ideas';
12 | import {
13 | PrimaryButton,
14 | SecondaryOutlinedButtonDark,
15 | } from '@/components/Buttons';
16 | import { useRouter } from 'next/router';
17 | import LayoutWrapper from '@/components/LayoutWrapper';
18 | import { insert_ideas_status } from '@/services/graphql/status';
19 | import { escape_new_line } from '@/services/util/string';
20 |
21 | export default function Registration() {
22 | const { isAuthenticated, isLoading } = useAuthenticationStatus();
23 | const [isDataLoading, setIsDataLoading] = useState(true);
24 | const [isSubmitting, setIsSubmitting] = useState(false);
25 | const [storedIdeaData, setStoredIdeaData] = useState({});
26 | const [formData, setFormData] = useState({});
27 | const router = useRouter();
28 |
29 | const userData = useUserData();
30 |
31 | const initializeData = () => {
32 | if (Object.keys(storedIdeaData).length === 0) {
33 | setIsDataLoading(true);
34 | const all_apis = [{ name: 'users', method: getAllUsers }];
35 | const promises = [];
36 | all_apis.forEach((api) => {
37 | promises.push(api.method());
38 | });
39 |
40 | Promise.all(promises)
41 | .then((res) => {
42 | res.forEach((rApi, rApi_ind) => {
43 | const api_obj = all_apis[rApi_ind];
44 | storedIdeaData[api_obj.name] = rApi;
45 | const anyField = FIELD_TEMPLATE.filter((field) => {
46 | return field.datafield === api_obj.name;
47 | });
48 | if (anyField.length) {
49 | anyField[0].options = rApi;
50 | }
51 | });
52 | setStoredIdeaData({ ...storedIdeaData });
53 | })
54 | .finally(() => {
55 | setIsDataLoading(false);
56 | });
57 | }
58 | };
59 |
60 | useEffect(() => {
61 | if (!isLoading) {
62 | if (!isAuthenticated) {
63 | if (typeof window !== 'undefined') {
64 | const protocol = process.env.NEXT_PUBLIC_PROTOCOL
65 | ? process.env.NEXT_PUBLIC_PROTOCOL
66 | : 'https';
67 | const host = window.location.hostname;
68 | const port = process.env.NEXT_PUBLIC_DEV_PORT
69 | ? `:${process.env.NEXT_PUBLIC_DEV_PORT}`
70 | : '';
71 | const external_path = NHOST.AUTH_URL(
72 | `${protocol}://${host}${port}/hackrplay/2022/registration`
73 | );
74 | window.location = external_path;
75 | }
76 | } else {
77 | initializeData();
78 | }
79 | }
80 | }, [isLoading]);
81 |
82 | if (isLoading) {
83 | return (
84 |
85 |
86 |
87 | Loading authentication information. Please wait.
88 |
89 |
90 |
91 | );
92 | }
93 |
94 | if (isDataLoading) {
95 | return (
96 |
97 |
98 |
99 | Checking authentication status. Please wait.
100 |
101 |
102 |
103 | );
104 | }
105 |
106 | const isFieldsAreInValid = () => {
107 | let res = false;
108 | FIELD_TEMPLATE.forEach((tmpl) => {
109 | if (tmpl.required && (!formData || !formData[tmpl.datafield])) {
110 | res = true;
111 | }
112 | });
113 | return res;
114 | };
115 |
116 | const onIdeaDataChanged = (data) => {
117 | setFormData({ ...data });
118 | setStoredIdeaData({ ...data });
119 | };
120 |
121 | const onSubmit = () => {
122 | setIsSubmitting(true);
123 | let idea_id = storedIdeaData.id;
124 | let selected_users = storedIdeaData.users;
125 | const idea_object = (({ title, description }) => ({
126 | title,
127 | description,
128 | }))(storedIdeaData);
129 | idea_object.owner = userData.id;
130 | idea_object.description = escape_new_line(idea_object.description);
131 | if (!idea_id)
132 | return insert_idea(idea_object).then((res) => {
133 | idea_id = res.id;
134 | const promises = [];
135 | if (selected_users && selected_users.length) {
136 | if (storedIdeaData.users) {
137 | promises.push(
138 | assign_member(idea_id, storedIdeaData.users)
139 | );
140 | }
141 | }
142 | formData.status = '63c47cd7-f9c4-41e1-87b6-7ebe7b59f00e';
143 | formData.id = idea_id;
144 | promises.push(insert_ideas_status(formData));
145 | return Promise.all(promises).then((res) => {
146 | router.push('ideas');
147 | setIsSubmitting(false);
148 | });
149 | });
150 | };
151 | const onCancelClicked = () => {
152 | router.back();
153 | };
154 |
155 | return (
156 |
157 |
158 |
159 |
160 |
161 |
163 | Registration
164 |
165 |
166 |
167 |
168 |
169 | Welcome{' '}
170 |
171 | {userData.displayName}
172 |
173 | , register your idea
174 |
175 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
191 | onCancelClicked()
192 | }>
193 | Cancel
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 | );
205 | }
206 |
--------------------------------------------------------------------------------
/components/Buttons.js:
--------------------------------------------------------------------------------
1 | export const PrimaryButton = ({
2 | children,
3 | handleOnClick,
4 | className,
5 | small = false,
6 | ...props
7 | }) => {
8 | const buttonSize = small
9 | ? "md:pt-1 md:pb-0 md:px-4 py-2 px-4 text-lg"
10 | : "md:py-4 md:px-7 py-3 px-5 text-xl";
11 |
12 | return (
13 |
18 | {children}
19 |
20 | );
21 | };
22 |
23 | export const PrimaryLink = ({
24 | children,
25 | link,
26 | className,
27 | target,
28 | small = false,
29 | ...props
30 | }) => {
31 | const buttonSize = small
32 | ? "md:pt-1 md:pb-0 md:px-4 py-2 px-4 text-lg"
33 | : "md:py-4 md:px-7 py-3 px-5 text-xl";
34 |
35 | return (
36 |
42 | {children}
43 |
44 | );
45 | };
46 |
47 | export const SecondaryButton = ({
48 | children,
49 | handleOnClick,
50 | className,
51 | small = false,
52 | }) => {
53 | const buttonSize = small
54 | ? "md:py-3 md:px-5 py-2 px-4 text-lg"
55 | : "md:py-4 md:px-7 py-3 px-5 text-xl";
56 |
57 | return (
58 |
62 | {children}
63 |
64 | );
65 | };
66 |
67 | export const SecondaryLink = ({
68 | children,
69 | link,
70 | className,
71 | target,
72 | small = false,
73 | }) => {
74 | const buttonSize = small
75 | ? "md:py-3 md:px-5 py-2 px-4 text-lg"
76 | : "md:py-4 md:px-7 py-3 px-5 text-xl";
77 |
78 | return (
79 |
84 | {children}
85 |
86 | );
87 | };
88 |
89 | export const SecondaryOutlinedButton = ({
90 | children,
91 | handleOnClick,
92 | small = false,
93 | }) => {
94 | const buttonSize = small
95 | ? "md:py-3 md:px-5 py-2 px-4 text-lg"
96 | : "md:py-4 md:px-7 py-3 px-5 text-xl";
97 |
98 | return (
99 |
103 | {children}
104 |
105 | );
106 | };
107 |
108 | export const SecondaryOutlinedButtonDark = ({ children, handleOnClick }) => {
109 | return (
110 |
114 | {children}
115 |
116 | );
117 | };
118 |
119 | export const ToolBarButton = ({
120 | children,
121 | handleOnClick,
122 | disabled,
123 | selected,
124 | cclas,
125 | }) => {
126 | return (
127 |
128 |
134 | {children}
135 |
136 |
137 | );
138 | };
139 |
--------------------------------------------------------------------------------
/components/Footer.js:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 |
3 | import FooterTriangles from "../public/FooterTriangles.svg";
4 | import ReactPlayLogo from "../public/ReactPlayLogo.svg";
5 | import FooterReactLogo from "../public/FooterReactLogo.svg";
6 | import { FaDiscord, FaTwitter, FaRss } from "react-icons/fa";
7 | import Link from "next/link";
8 |
9 | const Footer = () => {
10 | return (
11 |
71 | );
72 | };
73 |
74 | export default Footer;
75 |
--------------------------------------------------------------------------------
/components/Hack-R-Play/IdeaFilter.js:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { useState, useEffect } from "react";
3 | import Pagination from "@/components/Pagination";
4 | import SortButtons from "@/components/SortButtons";
5 | import OwnerFilter from "@/components/OwnerFilter";
6 | import StatusFilter from "../StatusFilter";
7 |
8 | export default function IdeaFilters({
9 | total,
10 | pagesize,
11 | onChange,
12 | isAuthenticated,
13 | }) {
14 | const [filter, setFilter] = useState({});
15 |
16 | useEffect(() => {}, [total]);
17 |
18 | const resetFilter = () => {
19 | filter.sort_col = "created_at";
20 | filter.sort_asc = true;
21 | filter.page = 1;
22 | filter.owner = "all";
23 | filter.pagesize = pagesize;
24 | filter.status_filter = undefined;
25 | return filter;
26 | };
27 |
28 | const onPageChanged = (index) => {
29 | const fl = resetFilter();
30 | fl.page = index;
31 | setFilter({ ...fl });
32 | invokeChange(fl);
33 | };
34 |
35 | const onOwnerChanged = (owner) => {
36 | const fl = resetFilter();
37 |
38 | fl.owner = owner;
39 | setFilter({ ...fl });
40 | invokeChange(fl);
41 | };
42 |
43 | const onSortChanged = (button) => {
44 | const fl = resetFilter();
45 | fl.sort_col = button.field;
46 | fl.sort_asc = button.asc;
47 | setFilter({ ...fl });
48 | invokeChange(fl);
49 | };
50 |
51 | const onStatusFilterChanged = (status) => {
52 | const fl = resetFilter();
53 | fl.status_filter = status;
54 | setFilter({ ...fl });
55 | invokeChange(fl);
56 | };
57 |
58 | const invokeChange = (filter) => {
59 | if (onChange) {
60 | onChange(filter);
61 | }
62 | };
63 |
64 | return (
65 |
66 | {isAuthenticated ? (
67 |
68 | onOwnerChanged(r)}
70 | selected={filter.owner}
71 | >
72 |
73 | ) : null}
74 |
75 | onStatusFilterChanged(r)}
77 | selected={filter.status_filter}
78 | >
79 |
80 |
81 |
onPageChanged(page)}
85 | >
86 |
onSortChanged(b)}
88 | buttons={[
89 | { label: "Date", field: "created_at" },
90 | { label: "Name", field: "title" },
91 | // { label: 'Popularity', field: 'liked' },
92 | ]}
93 | >
94 |
95 |
96 | );
97 | }
98 |
--------------------------------------------------------------------------------
/components/Hack-R-Play/index.js:
--------------------------------------------------------------------------------
1 | import Hero from "../common/Hero";
2 | import About from "../common/About";
3 | import ChallengesAndPrizes from "../common/ChallengesAndPrizes";
4 | import Judges from "../common/Judges";
5 | import Partners from "../common/Partners";
6 | import CTA from "../common/CTA";
7 | import FAQs from "../common/FAQs";
8 |
9 | export { Hero, About, ChallengesAndPrizes, Judges, Partners, CTA, FAQs };
10 |
--------------------------------------------------------------------------------
/components/Header.js:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 | import { useState } from "react";
3 | import { AiOutlineMenu, AiOutlineClose } from "react-icons/ai";
4 | import { PrimaryButton } from "./Buttons";
5 | import Image from "next/image";
6 |
7 | import { useRouter } from "next/router";
8 |
9 | const MobileHeader = ({ links, setMobileActive, redirectToRegistration }) => {
10 | return (
11 | <>
12 |
35 | >
36 | );
37 | };
38 |
39 | const Header = ({ links, metainfo, secondary = false }) => {
40 | const [mobileActive, setMobileActive] = useState(false);
41 | const router = useRouter();
42 | const redirectToRegistration = () => {
43 | router.push("/hackrplay/2022/registration");
44 | };
45 |
46 | return (
47 | <>
48 | {secondary ? (
49 |
62 | ) : (
63 |
81 | )}
82 | {!secondary && mobileActive && (
83 |
89 | )}
90 | >
91 | );
92 | };
93 |
94 | export default Header;
95 |
--------------------------------------------------------------------------------
/components/Ideas/Card.js:
--------------------------------------------------------------------------------
1 | import styles from '../../styles/idea.module.css';
2 | import Image from 'next/image';
3 | import { Grid, Card, Typography } from '@mui/material';
4 | import InProgress from '/public/Idea-List/inProgress.svg';
5 | import Complted from '/public/Idea-List/completed.svg';
6 | import NotStarted from '/public/Idea-List/notStart.svg';
7 | import { FiThumbsUp } from 'react-icons/fi';
8 | import { BiComment } from 'react-icons/bi';
9 |
10 | const IdeaCard = ({ data, onClick }) => {
11 | const get_status_style = (status) => {
12 | const final_status = status || { label: 'Idea Submitted' };
13 | switch (final_status.label) {
14 | case 'Completed':
15 | return {
16 | image: Complted,
17 | color: '#68FDC6',
18 | };
19 | case 'In Progress':
20 | return {
21 | image: InProgress,
22 | color: '#FDC668',
23 | };
24 | case 'Idea Submitted':
25 | default:
26 | return {
27 | image: NotStarted,
28 | color: '#FD6868',
29 | };
30 | }
31 | };
32 | return (
33 | onClick()}>
37 |
41 |
42 |
46 | {data.title}
47 |
48 |
49 |
50 |
54 |
58 |
59 |
63 | {data?.status?.label.toUpperCase() ||
64 | 'IDEA SUBMITTED'}
65 |
66 |
67 |
68 |
69 |
71 | {data.description}
72 |
73 |
74 |
75 |
82 | {data.avatarUrl.map((value, index) => {
83 | return (
84 |
92 | {value && (
93 |
103 | )}
104 |
105 | );
106 | })}
107 |
108 |
109 |
110 |
111 | {' '}
112 |
113 |
114 | {data.like_count}
115 |
116 |
117 |
118 |
119 |
120 | {data.comment_count}
121 |
122 |
123 |
124 |
125 |
126 | );
127 | };
128 | export default IdeaCard;
129 |
--------------------------------------------------------------------------------
/components/Layout.js:
--------------------------------------------------------------------------------
1 | import { ThemeConfig } from "@/services/consts/theme";
2 | import Head from "next/head";
3 | import { useRouter } from "next/router";
4 | import React, { useEffect, useState } from "react";
5 | import Footer from "./Footer";
6 | import Header from "./Header";
7 |
8 | const Layout = ({ children, title, description, metainfo }) => {
9 | const currentPath = useRouter().pathname;
10 | const [secondaryNavbar, setSecondaryNavbar] = useState(false);
11 | const [loading, setLoading] = useState(true);
12 |
13 | useEffect(() => {
14 | if (
15 | currentPath === "/events/23/hackrplay/2022/home" ||
16 | currentPath === "/events/23/twoplaysamonth"
17 | ) {
18 | setSecondaryNavbar(false);
19 | } else {
20 | setSecondaryNavbar(true);
21 | }
22 | if (metainfo?.name) {
23 | setLoading(false);
24 | }
25 | }, []);
26 |
27 | return (
28 | <>
29 | {!loading ? (
30 |
31 |
32 |
{title}
33 |
34 |
35 |
36 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
55 |
56 |
57 |
58 |
59 |
60 |
64 |
65 |
71 |
72 |
77 | {children}
78 |
79 |
80 | ) : null}
81 | >
82 | );
83 | };
84 |
85 | export default Layout;
86 |
--------------------------------------------------------------------------------
/components/LayoutWrapper.js:
--------------------------------------------------------------------------------
1 | import Layout from '@/components/Layout';
2 | import Flower from '../public/common/Flower.svg';
3 | import HeroLines from '../public/common/HeroLines.svg';
4 | import DottedAndFilledTriangle from '../public/common/DottedAndFilledTriangle.svg';
5 | import Image from 'next/image';
6 |
7 | const links = [
8 | {
9 | name: 'Home',
10 | href: '/',
11 | },
12 | {
13 | name: 'Submissions',
14 | href: '/hackrplay/2022/ideas',
15 | },
16 | ];
17 |
18 | export default function LayoutWrapper({ title, description, children}) {
19 | return (
20 |
21 |
22 |
28 |
29 |
30 |
31 |
32 |
33 |
39 |
40 | {children}
41 |
42 | );
43 | }
44 |
--------------------------------------------------------------------------------
/components/LinkLabel.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 |
3 | export const LinkLabel = ({ value, cclass, lclass }) => {
4 | const [htmlValue, setHtmlValue] = useState("");
5 | useEffect(() => {
6 | if (value) {
7 | const html = value
8 | .replace(/^### (.*$)/gim, "$1 ") // h3 tag
9 | .replace(/^## (.*$)/gim, "$1 ") // h2 tag
10 | .replace(/^# (.*$)/gim, "$1 ") // h1 tag
11 | .replace(/\*\*(.*)\*\*/gim, "$1 ") // bold text
12 | .replace(/\*(.*)\*/gim, "$1 ") // italic text
13 | .replace(/\r\n|\r|\n/gim, " ") // linebreaks
14 | .replace(
15 | /\[([^\[]+)\](\(([^)]*))\)/gim,
16 | `$1 `
17 | ); // anchor tags
18 | setHtmlValue(html);
19 | }
20 | }, [value]);
21 |
22 | return
;
23 | };
24 |
--------------------------------------------------------------------------------
/components/OwnerFilter.js:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { ToolBarButton } from "@/components/Buttons";
3 |
4 | export default function OwnerFilter({ onChange, selected }) {
5 | const [selectedButton, setSelectedButton] = React.useState("all");
6 |
7 | React.useEffect(() => {
8 | setSelectedButton(selected || "all");
9 | }, [selected]);
10 |
11 | const onButtonClicked = (type) => {
12 | setSelectedButton(type);
13 | if (onChange) {
14 | onChange(type);
15 | }
16 | };
17 |
18 | return (
19 |
20 | onButtonClicked("all")}
22 | // disabled={selected === "all" || selected === undefined}
23 | cclas={selectedButton === "all" ? `text-brand-hightlight` : ""}
24 | >
25 | All Ideas
26 |
27 | onButtonClicked("me")}
29 | // disabled={selected === "me"}
30 | cclas={selectedButton === "me" ? `text-brand-hightlight` : ""}
31 | >
32 | My Ideas
33 |
34 |
35 | );
36 | }
37 |
--------------------------------------------------------------------------------
/components/Pagination.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useState, useEffect } from 'react';
3 | import Button from '@mui/material/Button';
4 | import ButtonGroup from '@mui/material/ButtonGroup';
5 | import Box from '@mui/material/Box';
6 | import { FiChevronsLeft, FiChevronsRight } from 'react-icons/fi';
7 | import { ToolBarButton } from './Buttons';
8 |
9 | export default function Pagination({ total, pagesize, onChange }) {
10 | const [current, setCurrent] = useState(1);
11 | const [pageCount, setPageCount] = useState(0);
12 |
13 | useEffect(() => {
14 | setPageCount(Math.ceil(total / pagesize) || 1);
15 | setCurrent(1);
16 | }, [total]);
17 | const onButtonClicked = (index) => {
18 | setCurrent(index);
19 | invokeChange(index);
20 | };
21 | const invokeChange = (index) => {
22 | if (onChange) {
23 | onChange(index);
24 | }
25 | };
26 |
27 | return (
28 |
29 |
30 | onButtonClicked(current - 1)}
32 | disabled={current === 1}>
33 |
34 |
35 |
36 | Page: {current} / {pageCount}
37 |
38 | onButtonClicked(current + 1)}
40 | disabled={current === pageCount}>
41 |
42 |
43 |
44 |
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/components/SortButtons.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useState, useEffect } from 'react';
3 | import Button from '@mui/material/Button';
4 | import ButtonGroup from '@mui/material/ButtonGroup';
5 | import Box from '@mui/material/Box';
6 | import { FiArrowUp, FiArrowDown } from 'react-icons/fi';
7 | import { ToolBarButton } from '@/components/Buttons';
8 |
9 | export default function SortButtons({ buttons, selected, onChange }) {
10 | const [allButtons, setAllButtons] = useState([]);
11 | useEffect(() => {
12 | if (buttons.length) {
13 | allButtons.length = 0;
14 | buttons.forEach((b) => {
15 | const b_obj = {
16 | ...b,
17 | ...{
18 | asc: false,
19 | },
20 | };
21 | if (b.field === selected) {
22 | b.selected = false;
23 | }
24 | allButtons.push(b_obj);
25 | });
26 |
27 | if (selected === undefined) {
28 | allButtons[0].selected = true;
29 | setAllButtons([...allButtons]);
30 | }
31 | }
32 | }, []);
33 |
34 | const onButtonClicked = (button) => {
35 | const new_buttons = [];
36 | const selectedButton = {};
37 | allButtons.forEach((b) => {
38 | if (b.field === button.field) {
39 | if (b.selected) {
40 | b.asc = !b.asc;
41 | } else {
42 | b.selected = true;
43 | b.asc = true;
44 | }
45 | b.selected = true;
46 | selectedButton = { ...b };
47 | } else {
48 | b.selected = false;
49 | }
50 | new_buttons.push({ ...b });
51 | });
52 | setAllButtons(new_buttons);
53 |
54 | if (onChange) {
55 | onChange({ ...selectedButton });
56 | }
57 | };
58 |
59 | return (
60 |
61 | {allButtons.map((b, bi) => {
62 | return (
63 | onButtonClicked(b)}
67 | cclas={b.selected ? `text-brand-hightlight` : ''}>
68 | {b.label} {b.asc ? : }
69 |
70 | );
71 | })}
72 |
73 | );
74 | }
75 |
--------------------------------------------------------------------------------
/components/StatusFilter.js:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { ToolBarButton } from "@/components/Buttons";
3 |
4 | const STATUS_MAP = [
5 | {
6 | id: undefined,
7 | label: "All",
8 | },
9 | {
10 | id: "a177589f-25d9-4b67-adbd-310c1a8fc6e4",
11 | label: "Progressing",
12 | },
13 | {
14 | id: "ec1c0649-3b65-4809-92cf-9c4a6abdff1b",
15 | label: "Completed",
16 | },
17 | ];
18 | export default function StatusFilter({ onChange, selected }) {
19 | const [selectedButton, setSelectedButton] = React.useState(undefined);
20 |
21 | React.useEffect(() => {
22 | setSelectedButton(selected || undefined);
23 | }, [selected]);
24 |
25 | const onButtonClicked = (type) => {
26 | setSelectedButton(type);
27 | if (onChange) {
28 | onChange(type);
29 | }
30 | };
31 |
32 | return (
33 |
34 | {STATUS_MAP.map((sm, smi) => {
35 | return (
36 | onButtonClicked(sm.id)}
39 | cclas={selectedButton === sm.id ? `text-brand-hightlight` : ""}
40 | >
41 | {" "}
42 | {sm.label}
43 |
44 | );
45 | })}
46 |
47 | );
48 | }
49 |
--------------------------------------------------------------------------------
/components/common/About.js:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 |
3 | import ReactPlayDotted from "../../public/common/ReactPlayLogoDotted.svg";
4 | import Flower from "../../public/common/Flower.svg";
5 | import { FiExternalLink } from "react-icons/fi";
6 | import { ThemeConfig } from "@/services/consts/theme";
7 | import { LinkLabel } from "../LinkLabel";
8 |
9 | const About = ({ metainfo }) => {
10 | return (
11 | <>
12 | {metainfo.name ? (
13 |
17 |
18 |
19 |
24 |
25 |
26 |
27 | About this event
28 |
29 |
30 | {metainfo.about.texts[0]}
31 |
32 |
33 |
34 | {metainfo.about.texts[1]}
35 |
36 |
37 | {metainfo.about.bullets.map((b, b_i) => {
38 | return (
39 |
40 |
44 |
45 | );
46 | })}
47 |
48 |
49 |
53 |
54 | {/*
60 | Read More
61 | */}
62 |
63 |
64 |
65 |
69 |
72 | {metainfo.about.highlights[0]}
73 |
74 |
75 |
78 |
81 | {metainfo.about.highlights[1]}
82 |
83 |
84 |
89 |
92 | {metainfo.about.highlights[2]}
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | ) : null}
101 | >
102 | );
103 | };
104 |
105 | export default About;
106 |
--------------------------------------------------------------------------------
/components/common/CTA.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { SecondaryButton } from "../Buttons";
3 | import Image from "next/image";
4 | import { useRouter } from "next/router";
5 | import { FiPlus } from "react-icons/fi";
6 |
7 | const CTA = ({ image, metainfo }) => {
8 | const router = useRouter();
9 | const redirectToRegistration = () => {
10 | router.push("registration");
11 | };
12 |
13 | return (
14 |
18 |
19 |
20 |
21 |
28 |
29 |
30 |
31 | {metainfo.cta.title}
32 |
33 |
34 | {metainfo.cta.description}
35 |
36 |
37 |
38 |
39 |
40 | );
41 | };
42 |
43 | export default CTA;
44 |
--------------------------------------------------------------------------------
/components/common/ChallengesAndPrizes.js:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 |
3 | import GradientAndSmallTriangle from "../../public/common/GradientAndSmallTriangle.svg";
4 |
5 | const ChallengesAndPrizes = () => {
6 | return (
7 |
11 |
12 |
18 |
19 |
20 |
21 | Challenges & Prizes
22 |
23 |
24 |
25 |
26 |
27 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
28 | eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum
29 |
30 |
31 |
32 |
33 |
34 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
35 | eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum
36 |
37 |
38 |
39 |
40 |
41 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
42 | eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum
43 |
44 |
45 |
46 |
47 | );
48 | };
49 |
50 | export default ChallengesAndPrizes;
51 |
--------------------------------------------------------------------------------
/components/common/FAQs.js:
--------------------------------------------------------------------------------
1 | import { useState, useRef, useEffect } from "react";
2 |
3 | import { FiPlus, FiMinus } from "react-icons/fi";
4 |
5 | const FAQs = ({ metainfo }) => {
6 | const [active, setActive] = useState("false");
7 |
8 | const contentRef = useRef(null);
9 |
10 | useEffect(() => {
11 | contentRef.current.style.maxHeight = active
12 | ? `${contentRef.current.scrollHeight}px`
13 | : "0px";
14 | }, [contentRef, active]);
15 |
16 | const toggleAnswer = (index) => {
17 | if (active === index) {
18 | return setActive("0");
19 | }
20 | setActive(index);
21 | };
22 |
23 | return (
24 |
28 |
29 | FAQs
30 |
31 |
32 | {metainfo.faqs.map((faq, index) => (
33 |
37 |
toggleAnswer(index)}
39 | className="inline-flex justify-between items-center w-full cursor-pointer"
40 | >
41 |
42 | {faq.question}
43 |
44 | {active === index ? (
45 | toggleAnswer(index)}
48 | >
49 |
50 |
51 | ) : (
52 | toggleAnswer(index)}
55 | >
56 |
57 |
58 | )}
59 |
60 |
61 |
69 | {faq.answer}
70 |
71 |
72 | ))}
73 |
74 |
75 | );
76 | };
77 |
78 | export default FAQs;
79 |
--------------------------------------------------------------------------------
/components/common/Hero.js:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 |
3 | import {
4 | PrimaryButton,
5 | PrimaryLink,
6 | SecondaryLink,
7 | SecondaryOutlinedButton,
8 | } from "../Buttons";
9 | import { FiCheckCircle } from "react-icons/fi";
10 | import { BiRightArrowAlt } from "react-icons/bi";
11 |
12 | import Flower from "../../public/common/Flower.svg";
13 | import HeroLines from "../../public/common/HeroLines.svg";
14 | import RadialGradient from "../../public/common/RadialGradient.svg";
15 | import ReactPlayLogo from "../../public/ReactPlayLogo.svg";
16 | import { GiPartyPopper } from "react-icons/gi";
17 | import { useRouter } from "next/router";
18 | import { useEffect } from "react";
19 |
20 | const Hero = ({ metainfo }) => {
21 | const router = useRouter();
22 |
23 | useEffect(() => {}, [metainfo]);
24 | const redirectToRegistration = () => {
25 | router.push("registration");
26 | };
27 |
28 | const redirectToSubmissions = () => {
29 | router.push(metainfo.submissionurl);
30 | };
31 |
32 | return (
33 | <>
34 | {metainfo.name ? (
35 |
36 |
37 |
42 |
43 |
44 |
45 |
46 |
47 |
52 |
53 |
54 |
55 |
56 |
57 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
75 |
76 |
77 | {metainfo.subtitle}
78 |
79 |
80 |
81 | {metainfo.completed ? (
82 |
router.push("#winners")}>
83 | Winners
84 |
85 |
86 | ) : null}
87 | {metainfo.result_links ? (
88 |
89 | {metainfo.result_links.map((row, row_i) => {
90 | return (
91 |
92 | {row.map((link, link_i) => {
93 | return (
94 | <>
95 | {link.type === "primary" ? (
96 |
100 |
104 | {link.name}
105 |
106 |
107 | ) : (
108 |
109 |
113 | {link.name}
114 |
115 |
116 | )}
117 | >
118 | );
119 | })}
120 |
121 | );
122 | })}
123 |
124 | ) : null}
125 |
126 |
127 | {metainfo.started ? (
128 |
129 | redirectToSubmissions()}
131 | >
132 | View Submissions
133 |
137 |
138 |
139 | ) : null}
140 |
141 |
142 |
147 |
148 |
149 |
150 | ) : null}
151 | >
152 | );
153 | };
154 |
155 | export default Hero;
156 |
--------------------------------------------------------------------------------
/components/common/Judges.js:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 |
3 | import DottedPattern from "../../public/common/DottedPattern.svg";
4 | import Lines from "../../public/common/Lines.svg";
5 | import { FaTwitter } from "react-icons/fa";
6 | import { ThemeConfig } from "@/services/consts/theme";
7 |
8 | const Judges = ({ metainfo }) => {
9 | return (
10 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Judges & Mentors
28 |
29 |
30 | {metainfo.judges.map((judge, index) => (
31 |
62 | ))}
63 |
64 |
65 | );
66 | };
67 |
68 | export default Judges;
69 |
--------------------------------------------------------------------------------
/components/common/Partners.js:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 |
3 | const Partners = ({ metainfo }) => {
4 | if (!metainfo || !metainfo.partners) {
5 | return null;
6 | }
7 | return (
8 |
58 | );
59 | };
60 |
61 | export default Partners;
62 |
--------------------------------------------------------------------------------
/components/common/index.js:
--------------------------------------------------------------------------------
1 | export * from "./About";
2 | export * from "./CTA";
3 | export * from "./FAQs";
4 | export * from "./Judges";
5 | export * from "./Hero";
6 | export * from "./Partners";
7 | export * from "./Winners";
8 |
--------------------------------------------------------------------------------
/components/form-builder/index.js:
--------------------------------------------------------------------------------
1 | import { TextField, FormControl, Autocomplete, Box } from '@mui/material';
2 | import { useEffect, useState } from 'react';
3 | import * as _ from 'lodash';
4 | import { useUserData } from '@nhost/nextjs';
5 |
6 | const FormBuilder = ({ fields, data, onChange, disabled }) => {
7 | const userData = useUserData();
8 | const [formData, setFormData] = useState({});
9 | useEffect(() => {
10 | setFormData({ ...data });
11 | }, [data]);
12 |
13 | const onDataChanged = (key, value) => {
14 | formData[key] = value;
15 | setFormData({ ...formData });
16 | if (onChange) {
17 | onChange(formData);
18 | }
19 | };
20 |
21 | const getSelectedItem = (options, value) => {
22 | const item = options.find((opt) => {
23 | if (opt.id === value) return opt;
24 | });
25 | return item || '';
26 | };
27 |
28 | const renderField = (field) => {
29 | switch (field.type) {
30 | case 'input':
31 | return (
32 | {
41 | onDataChanged(field.datafield, e.target.value);
42 | }}
43 | />
44 | );
45 |
46 | case 'select':
47 | return (
48 |
53 | option.name || option[field.fieldName] || option
54 | }
55 | value={getSelectedItem(
56 | field.options,
57 | formData[field.datafield]
58 | )}
59 | disabled={disabled}
60 | filterSelectedOptions
61 | multiple={field.multiple}
62 | freeSolo={field.freeSolo}
63 | onChange={(e, newValue) => {
64 | let updatedval = newValue;
65 | onDataChanged(field.datafield, updatedval.id);
66 | }}
67 | renderInput={(params) => (
68 |
73 | )}
74 | />
75 | );
76 | case 'userlist':
77 | return (
78 |
79 |
u.id !== userData.id
86 | )
87 | : []
88 | }
89 | disabled={disabled}
90 | getOptionLabel={(option) =>
91 | option.name || option[field.fieldName] || option
92 | }
93 | filterSelectedOptions
94 | value={getSelectedItem(
95 | field.options,
96 | formData[field.datafield]
97 | )}
98 | multiple={field.multiple}
99 | freeSolo={field.freeSolo}
100 | renderOption={(props, option) => (
101 | img': { mr: 2, flexShrink: 0 } }}
104 | {...props}>
105 |
112 | {option.displayName}
113 |
114 | )}
115 | onChange={(e, newValue) => {
116 | let updatedval = newValue;
117 | onDataChanged(field.datafield, updatedval?.id);
118 | }}
119 | renderInput={(params) => (
120 |
121 |
126 |
127 | )}
128 | />
129 |
130 | You are already a member, select another person
131 | [optional] as your partner
132 |
133 |
134 | );
135 | default:
136 | return <>>;
137 | }
138 | };
139 |
140 | const renderForm = () => {
141 | return (
142 | <>
143 |
144 | {fields.map((field, field_key) => {
145 | return (
146 |
147 |
148 | {field.display}
149 | {field.required ? '*' : ''}
150 |
151 |
{renderField(field)}
152 |
153 | );
154 | })}
155 | {' '}
156 | >
157 | );
158 | };
159 |
160 | return <>{renderForm()}>;
161 | };
162 |
163 | export default FormBuilder;
164 |
--------------------------------------------------------------------------------
/components/interactions/index.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | import { useAuthenticationStatus, useUserData } from '@nhost/nextjs';
4 | import { TextField } from '@mui/material';
5 | import Snackbar from '@mui/material/Snackbar';
6 | import MuiAlert from '@mui/material/Alert';
7 | import Image from 'next/image';
8 | import styles from '@/styles/idea.module.css';
9 | import { useEffect, useState } from 'react';
10 | import { NHOST } from '@/services/nhost';
11 | import {
12 | PrimaryButton,
13 | SecondaryButton,
14 | SecondaryOutlinedButton,
15 | } from '../Buttons';
16 | import { insert_comment, like_idea } from '@/services/graphql/interactions';
17 | import { time_since } from '@/services/util/time';
18 | import { FiThumbsUp } from 'react-icons/fi';
19 | import { escape_new_line, unescape_new_line } from '@/services/util/string';
20 |
21 | const Alert = React.forwardRef(function Alert(props, ref) {
22 | return ;
23 | });
24 |
25 | const Interaction = ({ data, doRefresh }) => {
26 | const { isAuthenticated, isLoading } = useAuthenticationStatus();
27 | const [loading, setLoading] = useState();
28 | const userData = useUserData();
29 | const [commentText, setCommentText] = useState();
30 | const [isLiked, setIsLiked] = useState(false);
31 | const [alertOpen, setAlertOpen] = useState(false);
32 | const [alertMsg, setAlertMsg] = useState('');
33 |
34 | useEffect(() => {
35 | if (userData) {
36 | const filter_user = data.idea_like_map.filter(
37 | (lm) => lm.user_id === userData.id
38 | )[0];
39 | if (filter_user) {
40 | setIsLiked(true);
41 | }
42 | }
43 | }, [userData, data]);
44 | const onCommentSubmit = () => {
45 | setLoading(true);
46 | insert_comment(escape_new_line(commentText), data.id, userData.id).then(
47 | (res) => {
48 | setLoading(false);
49 | setAlertMsg('Successfully posted your comment');
50 | setAlertOpen(true);
51 | setCommentText('');
52 | if (doRefresh) {
53 | doRefresh();
54 | }
55 | }
56 | );
57 | };
58 |
59 | const onLikeClicked = () => {
60 | setLoading(true);
61 | like_idea(data.id, userData.id)
62 | .then((res) => {
63 | setLoading(false);
64 | setAlertMsg('You liked this idea');
65 | setAlertOpen(true);
66 | if (doRefresh) {
67 | doRefresh();
68 | }
69 | })
70 | .catch((err) => {
71 | // Do nothing
72 | if (doRefresh) {
73 | doRefresh();
74 | }
75 | });
76 | };
77 |
78 | const handleClose = (event, reason) => {
79 | if (reason === 'clickaway') {
80 | return;
81 | }
82 |
83 | setAlertOpen(false);
84 | };
85 |
86 | const onAuthenticate = () => {
87 | if (typeof window !== 'undefined') {
88 | const protocol = process.env.NEXT_PUBLIC_PROTOCOL
89 | ? process.env.NEXT_PUBLIC_PROTOCOL
90 | : 'https';
91 | const host = window.location.hostname;
92 | const port = process.env.NEXT_PUBLIC_DEV_PORT
93 | ? `:${process.env.NEXT_PUBLIC_DEV_PORT}`
94 | : '';
95 | const external_path = NHOST.AUTH_URL(
96 | `${protocol}://${host}${port}/hackrplay/2022/ideas/${data.id}`
97 | );
98 | window.location = external_path;
99 | }
100 | };
101 |
102 | if (isLoading) {
103 | return (
104 |
105 |
106 |
107 | Loading authentication information. Please wait.
108 |
109 |
110 |
111 | );
112 | }
113 |
114 | return (
115 |
116 |
117 |
118 | {data.idea_comments_map.length} COMMENT(S)
119 |
120 |
121 | {isAuthenticated ? (
122 | <>
123 | {isLiked ? (
124 |
125 |
129 | LIKED
130 |
131 | ) : (
132 |
onLikeClicked()}
134 | className='flex px-4 justify-center items-center text-white text-xl'>
135 | Like It
136 |
137 | )}
138 | >
139 | ) : null}
140 |
141 |
142 |
143 | {data.idea_comments_map.length === 0 ? (
144 |
145 | NO COMMENTS HAS BEEN ADDED
146 |
147 | ) : (
148 |
149 | {data.idea_comments_map.map((comment, ci) => {
150 | return (
151 |
152 |
153 |
154 |
155 |
168 |
169 |
170 | {
171 | comment
172 | .idea_comment_user_map
173 | .displayName
174 | }
175 |
176 |
177 | {time_since(
178 | new Date(comment.date)
179 | )}{' '}
180 | ago
181 |
182 |
183 |
184 | {unescape_new_line(comment.comment)}
185 |
186 |
187 |
188 | );
189 | })}
190 |
191 | )}
192 |
193 |
194 | {isAuthenticated ? (
195 |
196 |
197 |
198 |
199 |
200 |
209 |
210 |
211 | {userData.displayName}
212 |
213 |
214 |
215 |
217 |
223 | setCommentText(v.target.value)
224 | }
225 | value={commentText}
226 | />
227 |
228 |
229 |
230 |
onCommentSubmit()}>
235 | Comment
236 |
237 |
238 |
239 | ) : (
240 |
onAuthenticate()}
242 | className='w-full h-10 text-[#ffffff99] flex justify-center items-center rounded-md border-2 border-sky-400'>
243 | You need to login to comment or like ideas
244 |
245 | )}
246 |
247 |
251 |
255 | {alertMsg}
256 |
257 |
258 |
259 | );
260 | };
261 | export default Interaction;
262 |
--------------------------------------------------------------------------------
/components/status-bar/StatusBar.js:
--------------------------------------------------------------------------------
1 | import { TextField, FormControl, Autocomplete, Box } from '@mui/material';
2 | import { useEffect, useState } from 'react';
3 | import * as _ from 'lodash';
4 | import { useUserData } from '@nhost/nextjs';
5 | import Image from 'next/image';
6 | import { Typography } from '@mui/material';
7 | import styles from '@/styles/idea.module.css';
8 | import moment from 'moment';
9 |
10 | const StatusBar = ({ map, value }) => {
11 | return (
12 |
42 | );
43 | };
44 |
45 | export default StatusBar;
46 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "@/components/*": ["components/*"],
6 | "@/services/*": ["services/*"],
7 | "@/styles/*": ["styles/*"],
8 | "@/public/*": ["public/*"]
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | swcMinify: true,
5 | images: {
6 | domains: [
7 | 'avatars.githubusercontent.com',
8 | 'unavatar.io', // Gravatar
9 | 'pbs.twimg.com',
10 | ],
11 | },
12 | webpack: (config) => {
13 | config.module.rules.push({
14 | test: /\.(graphql|gql)$/,
15 | exclude: /node_modules/,
16 | loader: 'graphql-tag/loader',
17 | });
18 | return config;
19 | },
20 | }
21 |
22 | module.exports = nextConfig
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@emotion/react": "^11.10.4",
13 | "@emotion/server": "^11.10.0",
14 | "@emotion/styled": "^11.10.4",
15 | "@mui/material": "^5.10.4",
16 | "@nhost/nextjs": "^1.7.4",
17 | "@nhost/react": "^0.12.4",
18 | "confetti-js": "^0.0.18",
19 | "graphql": "^16.6.0",
20 | "json-graphql-parser": "^0.1.7",
21 | "lodash": "^4.17.21",
22 | "moment": "^2.29.4",
23 | "next": "12.2.5",
24 | "next-themes": "^0.2.1",
25 | "react": "18.2.0",
26 | "react-dom": "18.2.0",
27 | "react-icons": "^4.4.0"
28 | },
29 | "devDependencies": {
30 | "autoprefixer": "^10.4.8",
31 | "eslint": "8.23.0",
32 | "eslint-config-next": "12.2.5",
33 | "postcss": "^8.4.16",
34 | "tailwindcss": "^3.1.8"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | import { ThemeProvider } from "next-themes";
2 | import "../styles/globals.css";
3 |
4 | import { NhostNextProvider, NhostClient } from "@nhost/nextjs";
5 |
6 | const nhost = new NhostClient({
7 | subdomain: process.env.NEXT_PUBLIC_NHOST_SUBDOMAIN || "",
8 | region: process.env.NEXT_PUBLIC_NHOST_REGION || "",
9 | });
10 |
11 | function MyApp({ Component, pageProps }) {
12 | return (
13 |
14 |
15 |
16 |
17 |
18 | );
19 | }
20 |
21 | export default MyApp;
22 |
--------------------------------------------------------------------------------
/pages/api/hello.js:
--------------------------------------------------------------------------------
1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
2 |
3 | export default function handler(req, res) {
4 | res.status(200).json({ name: 'John Doe' })
5 | }
6 |
--------------------------------------------------------------------------------
/pages/events/22/hackrplay/ideas/index.js:
--------------------------------------------------------------------------------
1 | import IdeaCard from '@/components/Ideas/Card';
2 | import { useEffect, useState } from 'react';
3 | import { idea_count, list_ideas } from '@/services/graphql/ideas';
4 | import LayoutWrapper from '@/components/LayoutWrapper';
5 | import { CTA } from '@/components/Hack-R-Play';
6 | import gstyles from '@/styles/Home.module.css';
7 | import { Grid } from '@mui/material';
8 | import { useRouter } from 'next/router';
9 | import IdeaFilters from '@/components/Hack-R-Play/IdeaFilter';
10 | import { useAuthenticationStatus, useUserData } from '@nhost/nextjs';
11 | import { PrimaryButton } from '@/components/Buttons';
12 | import { get_latest_status } from '@/services/graphql/status';
13 | import { unescape_new_line } from '@/services/util/string';
14 |
15 | const PAGE_SIZE = 12;
16 |
17 | const IdeaListingPage = () => {
18 | const { isAuthenticated } = useAuthenticationStatus();
19 | const [ideas, setIdeas] = useState([]);
20 | const [ideaCount, setIdeaCount] = useState(0);
21 | const [isLoading, setIsLoading] = useState(false);
22 | const router = useRouter();
23 | const userData = useUserData();
24 |
25 | useEffect(() => {
26 | loadIdeas();
27 | }, []);
28 |
29 | const loadIdeas = (filter) => {
30 | setIsLoading(true);
31 | const promises = [];
32 | console.log(filter);
33 | promises.push(
34 | list_ideas(filter || { pagesize: PAGE_SIZE }, userData?.id).then(
35 | (res) => {
36 | if (res && res.length) {
37 | res.forEach((i) => {
38 | i.description = unescape_new_line(i.description);
39 | });
40 | }
41 | return res;
42 | }
43 | )
44 | );
45 | promises.push(idea_count(filter, userData?.id));
46 |
47 | Promise.all(promises)
48 | .then((res) => {
49 | processResultData(res[0]);
50 | setIdeaCount(res[1]);
51 | setIsLoading(false);
52 | })
53 | .catch((err) => {
54 | console.error(err);
55 | });
56 | };
57 |
58 | const onCardClicked = (id) => {
59 | router.push(`ideas/${id}`);
60 | };
61 |
62 | const redirectToRegistration = () => {
63 | router.push('registration');
64 | };
65 |
66 | const processResultData = (result) => {
67 | let tempData = [];
68 | for (const idea of result) {
69 | let interObj = {
70 | title: idea.title,
71 | description: idea.description,
72 | id: idea.id,
73 | comment_count: idea.idea_comments_map_aggregate.aggregate.count,
74 | like_count: idea.idea_like_map_aggregate.aggregate.count,
75 | avatarUrl: [
76 | idea.idea_members_map?.user_id_map.avatarUrl,
77 | idea.idea_owner_map?.avatarUrl,
78 | ],
79 | tinkers: [
80 | idea.idea_members_map?.user_id_map.displayName,
81 | idea.dea_owner_map?.displayName,
82 | ],
83 | status: get_latest_status(idea),
84 | };
85 |
86 | tempData.push(interObj);
87 | }
88 | setIdeas(tempData);
89 | };
90 |
91 | return (
92 |
95 |
96 |
97 |
99 | SUBMISSIONS
100 |
101 |
102 | {' '}
103 | Total: {ideaCount}
104 |
105 |
106 |
107 | loadIdeas(f)}>
112 |
113 |
114 |
123 | {ideas.length === 0 ? (
124 |
125 |
126 | No idea has been added yet.
127 |
128 |
129 | ) : (
130 | <>
131 | {ideas.map((value, vi) => {
132 | return (
133 |
142 |
145 | onCardClicked(value.id)
146 | }
147 | />
148 |
149 | );
150 | })}
151 | >
152 | )}
153 |
154 |
155 |
159 |
160 |
161 | );
162 | };
163 |
164 | export default IdeaListingPage;
165 |
--------------------------------------------------------------------------------
/pages/events/22/hackrplay/ideas/submit/[id].js:
--------------------------------------------------------------------------------
1 | import { useAuthenticationStatus, useUserData } from '@nhost/nextjs';
2 | import styles from '@/styles/Home.module.css';
3 |
4 | import { FiCheckCircle } from 'react-icons/fi';
5 | import { NHOST } from '@/services/nhost';
6 | import { useEffect, useState, forwardRef } from 'react';
7 | import FormBuilder from '@/components/form-builder';
8 | import { FIELD_TEMPLATE } from '@/services/consts/submission-fields';
9 | import { getAllUsers } from '@/services/graphql/auth';
10 | import { get_idea, insert_idea_submission } from '@/services/graphql/ideas';
11 | import {
12 | PrimaryButton,
13 | SecondaryOutlinedButtonDark,
14 | } from '@/components/Buttons';
15 | import { useRouter } from 'next/router';
16 | import LayoutWrapper from '@/components/LayoutWrapper';
17 | import Snackbar from '@mui/material/Snackbar';
18 | import MuiAlert from '@mui/material/Alert';
19 | import { submit } from 'json-graphql-parser/v2';
20 | import {
21 | insert_ideas_status,
22 | list_statuses,
23 | update_ideas_status,
24 | get_latest_status,
25 | } from '@/services/graphql/status';
26 | import { escape_new_line } from '@/services/util/string';
27 |
28 | const Alert = forwardRef(function Alert(props, ref) {
29 | return ;
30 | });
31 |
32 | export default function SubmitIdea() {
33 | const { isAuthenticated, isLoading } = useAuthenticationStatus();
34 | const [userId, setUserId] = useState('');
35 | const [isDataLoading, setIsDataLoading] = useState(true);
36 | const [isSubmitting, setIsSubmitting] = useState(false);
37 | const [ideaObject, setIdeaObject] = useState({});
38 | const [alertOpen, setAlertOpen] = useState(false);
39 | const [pageDisabled, setPageDisabled] = useState(false);
40 |
41 | const userData = useUserData();
42 | const router = useRouter();
43 | const { id } = router.query;
44 |
45 | const initializeData = () => {
46 | setIsDataLoading(true);
47 | get_idea(id).then((r) => {
48 | const status = get_latest_status(r);
49 | if (userData.id !== r.idea_owner_map.id) {
50 | setAlertOpen(true);
51 | setPageDisabled(true);
52 | }
53 | if (
54 | status &&
55 | status.id === process.env.NEXT_PUBLIC_HACKATHON_SUBMIT_STATUS_ID
56 | ) {
57 | router.push('../../ideas');
58 | } else {
59 | setIdeaObject(r);
60 | setIsDataLoading(false);
61 | }
62 | });
63 | };
64 |
65 | useEffect(() => {
66 | if (!isLoading) {
67 | if (!isAuthenticated) {
68 | if (typeof window !== 'undefined') {
69 | const protocol = process.env.NEXT_PUBLIC_PROTOCOL
70 | ? process.env.NEXT_PUBLIC_PROTOCOL
71 | : 'https';
72 | const host = window.location.hostname;
73 | const port = process.env.NEXT_PUBLIC_DEV_PORT
74 | ? `:${process.env.NEXT_PUBLIC_DEV_PORT}`
75 | : '';
76 | const external_path = NHOST.AUTH_URL(
77 | `${protocol}://${host}${port}/hackrplay/2022/submit/${id}`
78 | );
79 | window.location = external_path;
80 | }
81 | } else {
82 | initializeData();
83 | }
84 | }
85 | }, [isLoading]);
86 |
87 | if (isLoading) {
88 | return (
89 |
90 |
91 |
92 | Loading authentication information. Please wait.
93 |
94 |
95 |
96 | );
97 | }
98 |
99 | if (isDataLoading) {
100 | return (
101 |
102 |
103 |
104 | Checking authentication status. Please wait.
105 |
106 |
107 |
108 | );
109 | }
110 |
111 | const isFieldsAreInValid = () => {
112 | let res = false;
113 | FIELD_TEMPLATE.forEach((tmpl) => {
114 | if (tmpl.required && (!ideaObject || !ideaObject[tmpl.datafield])) {
115 | res = true;
116 | }
117 | });
118 | return res;
119 | };
120 |
121 | const onIdeaDataChanged = (data) => {
122 | setIdeaObject({ ...data });
123 | };
124 |
125 | const onSubmit = () => {
126 | setIsSubmitting(true);
127 | ideaObject.status = process.env.NEXT_PUBLIC_HACKATHON_SUBMIT_STATUS_ID;
128 | ideaObject.comment = escape_new_line(ideaObject.comment);
129 | console.log(ideaObject);
130 | Promise.all([
131 | insert_idea_submission(ideaObject),
132 | insert_ideas_status(ideaObject),
133 | ]).then((res) => {
134 | router.push('..');
135 | });
136 | };
137 | const onCancelClicked = () => {
138 | router.push('..');
139 | };
140 |
141 | return (
142 |
143 |
144 |
145 |
146 |
147 |
149 | Idea Submission
150 |
151 |
152 |
153 | {alertOpen ? (
154 |
155 | You cannot submit this idea. Only author can
156 | edit an idea.
157 |
158 | ) : (
159 |
160 | Congratulations{' '}
161 | {userData.displayName} for
162 | completing your idea for HACK-R-PLAY
163 |
164 | )}
165 |
166 |
167 |
168 |
169 | Idea Title :{' '}
170 |
171 |
{ideaObject.title}
172 |
173 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
191 | onCancelClicked()
192 | }>
193 | Cancel
194 |
195 |
196 |
197 |
198 |
onSubmit()}>
204 | Submit
205 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 | );
219 | }
220 |
--------------------------------------------------------------------------------
/pages/events/22/hackrplay/index.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import { useRouter } from "next/router";
3 | import Layout from "@/components/Layout";
4 | import Image from "next/image";
5 | import { useTheme } from "next-themes";
6 | // import { Hero, About, Judges, CTA, FAQs } from "@/components/common";
7 | import About from "@/components/common/About";
8 | import Judges from "@/components/common/Judges";
9 | import Hero from "@/components/common/Hero";
10 | import Partners from "@/components/common/Partners";
11 | import CTA from "@/components/common/CTA";
12 | import FAQs from "@/components/common/FAQs";
13 |
14 | import DottedAndFilledTriangle from "@/public/common/DottedAndFilledTriangle.svg";
15 | import Flower from "@/public/common/Flower.svg";
16 | import { Config } from "@/services/metadata/hackrplay";
17 | import Winners from "@/components/common/Winners";
18 |
19 | export default function Home() {
20 | const router = useRouter();
21 | const [mounted, setMounted] = useState(false);
22 | const { theme, setTheme } = useTheme("hackrplay");
23 | useEffect(() => {
24 | setTheme("hackrplay");
25 | setMounted(true);
26 | }, []);
27 |
28 | const winners = [];
29 | const mentions = [];
30 |
31 | if (!mounted) return null;
32 |
33 | return (
34 |
35 |
36 |
41 |
42 |
43 |
44 |
45 |
46 | {Config.completed ? (
47 |
48 | ) : null}
49 |
50 |
51 | {Config.partners ? : null}
52 | {Config.cta ? : null}
53 |
54 | {Config.faqs ? : null}
55 |
56 | );
57 | }
58 |
--------------------------------------------------------------------------------
/pages/events/23/twoplaysamonth/index.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import { useRouter } from "next/router";
3 | import Layout from "@/components/Layout";
4 | import Image from "next/image";
5 | import { useTheme } from "next-themes";
6 | // import { Hero, About, Judges, CTA, FAQs } from "@/components/common";
7 | import About from "@/components/common/About";
8 | import Judges from "@/components/common/Judges";
9 | import Hero from "@/components/common/Hero";
10 | import Partners from "@/components/common/Partners";
11 | import CTA from "@/components/common/CTA";
12 | import FAQs from "@/components/common/FAQs";
13 |
14 | import DottedAndFilledTriangle from "@/public/common/DottedAndFilledTriangle.svg";
15 | import Flower from "@/public/common/Flower.svg";
16 | import { Config } from "@/services/metadata/twoplaysamonth";
17 | import Winners from "@/components/common/Winners";
18 |
19 | export default function Home() {
20 | const router = useRouter();
21 | const [mounted, setMounted] = useState(false);
22 | const { theme, setTheme } = useTheme("twoplaysamonth");
23 | useEffect(() => {
24 | setTheme("twoplaysamonth");
25 | setMounted(true);
26 | }, []);
27 |
28 | const winners = [];
29 | const mentions = [];
30 |
31 | if (!mounted) return null;
32 |
33 | return (
34 |
35 |
36 |
41 |
42 |
43 |
44 |
45 |
46 | {Config.completed ? (
47 |
48 | ) : null}
49 |
50 |
51 | {Config.partners ? : null}
52 | {Config.cta ? : null}
53 |
54 | {Config.faqs ? : null}
55 |
56 | );
57 | }
58 |
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import { useRouter } from "next/router";
3 | import Layout from "@/components/Layout";
4 |
5 | export default function Home() {
6 | const router = useRouter();
7 | useEffect(() => {
8 | router.push("events/23/twoplaysamonth");
9 | }, []);
10 |
11 | return ;
12 | }
13 |
--------------------------------------------------------------------------------
/pages/tech-credit.js:
--------------------------------------------------------------------------------
1 | import Layout from "../components/Layout";
2 | import Image from "next/image";
3 | import Link from "next/link";
4 | import TailWindLogo from "../public/tailwindcss-logotype.svg";
5 | import NextJsLogo from "../public/Nextjs-logo.png";
6 |
7 | const TechCreditPage = () => {
8 | return (
9 |
13 |
14 |
15 | Tech Stack
16 |
17 |
48 |
49 |
50 | Credits
51 |
52 |
72 |
73 |
74 | );
75 | };
76 |
77 | export default TechCreditPage;
78 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/2plays-a-month/og-image-twoplaysamonth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/2plays-a-month/og-image-twoplaysamonth.png
--------------------------------------------------------------------------------
/public/FooterReactLogo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/public/FooterTriangles.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/public/Idea-List/completed.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/public/Idea-List/inProgress.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/public/Idea-List/notStart.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/public/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/Logo.png
--------------------------------------------------------------------------------
/public/Nextjs-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/Nextjs-logo.png
--------------------------------------------------------------------------------
/public/ReactPlayLogo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/common/DottedPattern.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/public/common/Flower.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/public/common/GradientAndSmallTriangle.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/public/common/HeroLines.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/public/common/Lines.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/public/common/RadialGradient.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/favicon.png
--------------------------------------------------------------------------------
/public/hackrplay/BannerLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/hackrplay/BannerLogo.png
--------------------------------------------------------------------------------
/public/hackrplay/GradientAndSmallTriangle.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/public/hackrplay/GradientFlower.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/hackrplay/NavbarLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/hackrplay/NavbarLogo.png
--------------------------------------------------------------------------------
/public/hackrplay/NhostLogo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/public/hackrplay/og-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/hackrplay/og-image.png
--------------------------------------------------------------------------------
/public/hackrplay/partner0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/hackrplay/partner0.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # Allow all user agents.
2 | User-agent: *
3 | Allow: /
4 |
5 | # User agent "Googlebot" should not crawl the `http://example.com/nogooglebot/` folder or any of its subdirectories.
6 | User-agent: Googlebot
7 | Disallow: /nogooglebot/
--------------------------------------------------------------------------------
/public/tailwindcss-logotype.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/twoplaysamonth/BannerLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/twoplaysamonth/BannerLogo.png
--------------------------------------------------------------------------------
/public/twoplaysamonth/GradientAndSmallTriangle.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/twoplaysamonth/GradientFlower.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/public/twoplaysamonth/NavbarLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/twoplaysamonth/NavbarLogo.png
--------------------------------------------------------------------------------
/public/twoplaysamonth/og-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/twoplaysamonth/og-image.png
--------------------------------------------------------------------------------
/public/twoplaysamonth/partner0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/public/twoplaysamonth/partner0.png
--------------------------------------------------------------------------------
/public/twoplaysamonth/partner0.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/services/consts/registration-fields.js:
--------------------------------------------------------------------------------
1 | export const FIELD_TEMPLATE = [
2 | {
3 | datafield: "title",
4 | type: "input",
5 | display: "Title",
6 | placeholder: "Idea title",
7 | required: true,
8 | },
9 | {
10 | datafield: "description",
11 | type: "input",
12 | display: "Description",
13 | placeholder: "Describe your idea",
14 | required: true,
15 | rows: 10,
16 | multiline: true,
17 | },
18 | ,
19 | {
20 | datafield: "users",
21 | type: "userlist",
22 | display: "Member",
23 | placeholder: "Select team members",
24 | options: [],
25 | fieldName: "displayName",
26 | },
27 | ];
28 |
--------------------------------------------------------------------------------
/services/consts/registration-update-fields.js:
--------------------------------------------------------------------------------
1 | export const FIELD_TEMPLATE = [
2 | {
3 | datafield: "title",
4 | type: "input",
5 | display: "Title",
6 | placeholder: "Idea title",
7 | required: true,
8 | },
9 | {
10 | datafield: "description",
11 | type: "input",
12 | display: "Description",
13 | placeholder: "Describe your idea",
14 | required: true,
15 | rows: 10,
16 | multiline: true,
17 | },
18 | ,
19 | {
20 | datafield: "users",
21 | type: "userlist",
22 | display: "Member",
23 | placeholder: "Select team members",
24 | options: [],
25 | fieldName: "displayName",
26 | },
27 | {
28 | datafield: "status",
29 | type: "select",
30 | display: "Status",
31 | placeholder: "Status",
32 | options: [],
33 | fieldName: "label",
34 | fieldValue: "id",
35 | },
36 | ];
37 |
--------------------------------------------------------------------------------
/services/consts/submission-fields.js:
--------------------------------------------------------------------------------
1 | export const FIELD_TEMPLATE = [
2 | {
3 | datafield: 'repository',
4 | type: 'input',
5 | display: 'Source Code Repository',
6 | placeholder: 'Must be public repository url',
7 | required: true,
8 | },
9 | {
10 | datafield: 'application',
11 | type: 'input',
12 | display: 'Application URL',
13 | placeholder: 'URL information where application in hosted',
14 | required: true,
15 | },
16 | {
17 | datafield: 'blog',
18 | type: 'input',
19 | display: 'Article URL',
20 | placeholder: 'Give URL of your application article',
21 | required: true,
22 | },
23 |
24 | {
25 | datafield: 'comment',
26 | type: 'input',
27 | display: 'Comment',
28 | placeholder: 'Comment if any',
29 |
30 | rows: 10,
31 | multiline: true,
32 | },
33 | ];
34 |
--------------------------------------------------------------------------------
/services/consts/theme.js:
--------------------------------------------------------------------------------
1 | export const ThemeConfig = {
2 | twoplaysamonth: {
3 | background: "#1D1455",
4 | textHighlight: "#CCF381",
5 | judgesBg: "#684EFF",
6 | boxes: ["#4831D4", "#FFFFFF", "#CCF381"],
7 | },
8 | "Hack-R-Play": {
9 | background: "#051630",
10 | textHighlight: "#00F2FE",
11 | judgesBg: "#1D1455",
12 | boxes: ["#68FDC6", "#FFFFFF", "#00F2FE"],
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/services/graphql/auth.js:
--------------------------------------------------------------------------------
1 | import { submit } from "@/services/request";
2 | import * as _ from "lodash";
3 |
4 | export const getAllUsers = () => {
5 | return submit({
6 | display: "All Users",
7 | name: "Users",
8 | function: "users",
9 | return: ["avatarUrl", "displayName", "id"],
10 | }).then((res) => {
11 | return _.orderBy(res, ["displayName"], ["asc"]);
12 | });
13 | };
14 |
--------------------------------------------------------------------------------
/services/graphql/ideas.js:
--------------------------------------------------------------------------------
1 | import { submit } from "@/services/request";
2 | import * as _ from "lodash";
3 | import { FaClosedCaptioning } from "react-icons/fa";
4 | import { insert_ideas_status } from "./status";
5 |
6 | export const createIdeaQuery = {
7 | display: "Insert Idea",
8 | name: "Insert_Hackathon_Ideas_One",
9 | function: "insert_hackathon_ideas_one",
10 | write: true,
11 | object: {},
12 | return: ["id"],
13 | };
14 |
15 | export const assignIdeaMembers = {
16 | display: "Insert Idea",
17 | name: "Insert_Hackathon_Ideas_Members",
18 | function: "insert_hackathon_ideas_members_one",
19 | write: true,
20 | object: {},
21 | return: ["id"],
22 | };
23 |
24 | export const insert_idea = (idea_object) => {
25 | const input_obj = { ...createIdeaQuery, ...{ object: idea_object } };
26 | input_obj.object.hackathon_id = process.env.NEXT_PUBLIC_HACKATHON_ID;
27 | return submit(input_obj);
28 | };
29 |
30 | export const assign_member = (idea_id, user_id) => {
31 | const input_obj = {
32 | ...assignIdeaMembers,
33 | ...{
34 | object: {
35 | idea_id: idea_id,
36 | user_id: user_id,
37 | },
38 | },
39 | };
40 | return submit(input_obj);
41 | };
42 |
43 | export const idea_count = (filter, current_user) => {
44 | const input_obj = {
45 | display: "Count Ideas",
46 | name: "Hackathon_Ideas_Aggregate",
47 | function: "hackathon_ideas_aggregate",
48 | return: [{ aggregate: ["count"] }],
49 | };
50 | if (filter && filter.owner && filter.owner === "me" && current_user) {
51 | input_obj.where = {
52 | clause: {
53 | class: "idea_owner_map",
54 | operator: "and",
55 | conditions: [
56 | {
57 | field: "id",
58 | operator: "eq",
59 | value: current_user,
60 | },
61 | ],
62 | },
63 | };
64 | }
65 |
66 | if (filter && filter.status_filter) {
67 | input_obj.where = {
68 | clause: {
69 | class: "idea_idea_status_map",
70 | operator: "and",
71 | conditions: [
72 | {
73 | field: "status_id",
74 | operator: "eq",
75 | value: filter.status_filter,
76 | },
77 | ],
78 | },
79 | };
80 | }
81 |
82 | return submit(input_obj).then((res) => {
83 | return res && res.aggregate ? res.aggregate.count : 0;
84 | });
85 | };
86 |
87 | export const list_ideas = (filter, current_user) => {
88 | const input_obj = {
89 | display: "List Ideas",
90 | name: "hackathon_ideas",
91 | function: "hackathon_ideas",
92 | orders: [{ field: "created_at", value: "desc" }],
93 | return: [
94 | "description",
95 | "title",
96 | "created_at",
97 | "id",
98 | {
99 | idea_idea_status_map: {
100 | idea_status_status_map: ["label"],
101 | },
102 | },
103 | {
104 | "idea_members_map ": [
105 | "id",
106 | {
107 | user_id_map: ["avatarUrl", "displayName"],
108 | },
109 | ],
110 | },
111 | {
112 | idea_owner_map: ["avatarUrl", "displayName"],
113 | },
114 | {
115 | idea_comments_map_aggregate: {
116 | aggregate: ["count"],
117 | },
118 | },
119 | {
120 | idea_like_map_aggregate: {
121 | aggregate: ["count"],
122 | },
123 | },
124 | ],
125 | distinct: "id",
126 | };
127 | if (filter.pagesize) {
128 | input_obj.limit = filter.pagesize;
129 | }
130 | if (filter.page) {
131 | input_obj.offset = (filter.page - 1) * filter.pagesize;
132 | }
133 |
134 | if (filter.sort_col) {
135 | input_obj.orders = [
136 | {
137 | field: filter.sort_col,
138 | value:
139 | filter.sort_asc === undefined || filter.sort_asc ? "asc" : "desc",
140 | },
141 | ];
142 | }
143 | if (filter.status_filter) {
144 | input_obj.where = {
145 | clause: {
146 | class: "idea_idea_status_map",
147 | operator: "and",
148 | conditions: [
149 | {
150 | field: "status_id",
151 | operator: "eq",
152 | value: filter.status_filter,
153 | },
154 | ],
155 | },
156 | };
157 | }
158 |
159 | if (filter.owner && filter.owner === "me" && current_user) {
160 | input_obj.where = {
161 | clause: {
162 | class: "idea_owner_map",
163 | operator: "and",
164 | conditions: [
165 | {
166 | field: "id",
167 | operator: "eq",
168 | value: current_user,
169 | },
170 | ],
171 | },
172 | };
173 | }
174 |
175 | return submit(input_obj).then((res) => {
176 | const s_col = filter && filter.sort_col ? filter.sort_col : "created_at";
177 | const s_type = filter && filter.sort_asc ? filter.sort_asc : false;
178 | let sorted = [];
179 | // if (sort_col === 'liked') {
180 | // sorted = _.orderBy(
181 | // res,
182 | // [(element) => element.idea_like_map_aggregate.aggregate.count],
183 | // [s_type ? 'asc' : 'desc']
184 | // );
185 | // } else {
186 | sorted = _.orderBy(
187 | res,
188 | [(element) => element[s_col].toLowerCase()],
189 | [s_type ? "asc" : "desc"]
190 | );
191 | // }
192 | return sorted;
193 | });
194 | };
195 |
196 | export const get_idea = (id) => {
197 | const input_obj = {
198 | display: "List Ideas",
199 | name: "hackathon_ideas",
200 | function: "hackathon_ideas",
201 | where: {
202 | clause: {
203 | operator: "and",
204 | conditions: [
205 | {
206 | field: "id",
207 | operator: "eq",
208 | value: id,
209 | },
210 | ],
211 | },
212 | },
213 |
214 | return: [
215 | "description",
216 | "title",
217 | "id",
218 | {
219 | idea_idea_status_map: [
220 | "date",
221 | { idea_status_status_map: ["label", "id"] },
222 | ],
223 | },
224 | {
225 | "idea_members_map ": [
226 | "id",
227 | {
228 | user_id_map: ["avatarUrl", "displayName", "id"],
229 | },
230 | ],
231 | },
232 | {
233 | idea_owner_map: ["avatarUrl", "displayName", "id"],
234 | },
235 | {
236 | idea_comments_map_aggregate: {
237 | aggregate: ["count"],
238 | },
239 | },
240 | {
241 | idea_like_map_aggregate: {
242 | aggregate: ["count"],
243 | },
244 | },
245 | {
246 | idea_comments_map: [
247 | "comment",
248 | "date",
249 | { idea_comment_user_map: ["displayName", "avatarUrl"] },
250 | ],
251 | },
252 | {
253 | idea_like_map: ["user_id"],
254 | },
255 | ],
256 | };
257 | return submit(input_obj).then((res) => {
258 | return res[0];
259 | });
260 | };
261 |
262 | export const update_ideas_demographic = (idea_object) => {
263 | const insert_obj = {
264 | display: "Update Idea",
265 | name: "Update_Hackathon_Ideas",
266 | function: "update_hackathon_ideas",
267 | write: true,
268 | value: {
269 | title: idea_object.title,
270 | description: idea_object.description,
271 | },
272 | where: {
273 | clause: {
274 | operator: "and",
275 | conditions: [
276 | {
277 | field: "id",
278 | operator: "eq",
279 | value: idea_object.id,
280 | },
281 | ],
282 | },
283 | },
284 | return: ["affected_rows"],
285 | };
286 |
287 | return submit(insert_obj);
288 | };
289 |
290 | export const update_ideas_member = (idea_object) => {
291 | let insert_obj = undefined;
292 |
293 | if (idea_object.users) {
294 | if (!idea_object.idea_members_map) {
295 | insert_obj = {
296 | display: "Insert Idea Member",
297 | name: "Insert_Hackathon_Ideas_Members_One",
298 | function: "insert_hackathon_ideas_members_one",
299 | write: true,
300 | object: {
301 | idea_id: idea_object.id,
302 | user_id: idea_object.users,
303 | },
304 | return: ["id"],
305 | };
306 | } else {
307 | insert_obj = {
308 | display: "Update Idea Member",
309 | name: "Update_Hackathon_Ideas_Members",
310 | function: "update_hackathon_ideas_members",
311 | write: true,
312 | value: {
313 | idea_id: idea_object.id,
314 | user_id: idea_object.users,
315 | },
316 | where: {
317 | clause: {
318 | operator: "and",
319 | conditions: [
320 | {
321 | field: "id",
322 | operator: "eq",
323 | value: idea_object.idea_members_map.id,
324 | },
325 | ],
326 | },
327 | },
328 | return: ["affected_rows"],
329 | };
330 | }
331 | return submit(insert_obj);
332 | }
333 | };
334 |
335 | export const insert_idea_submission = (idea_object) => {
336 | console.log(idea_object);
337 |
338 | idea_object.status = process.env.NEXT_PUBLIC_HACKATHON_SUBMIT_STATUS_ID;
339 | const insert_submission = {
340 | display: "Insert Idea Submission",
341 | name: "Insert_Hackathon_Idea_Submission_One",
342 | function: "insert_hackathon_idea_submission_one",
343 | write: true,
344 | object: {
345 | idea_id: idea_object.id,
346 | repository_url: idea_object.repository,
347 | blog_url: idea_object.blog,
348 | application: idea_object.application,
349 | comment: idea_object.comment,
350 | },
351 | return: ["id"],
352 | };
353 |
354 | return submit(insert_submission);
355 | };
356 |
--------------------------------------------------------------------------------
/services/graphql/interactions.js:
--------------------------------------------------------------------------------
1 | import { submit } from '@/services/request';
2 | import * as _ from 'lodash';
3 |
4 | export const insert_comment = (comment, idea_id, current_user) => {
5 | const input_obj = {
6 | display: 'Insert Comment',
7 | name: 'Insert_Hackathon_Idea_Comments_One',
8 | function: 'insert_hackathon_idea_comments_one',
9 | write: true,
10 | object: {
11 | hackathon_id: process.env.NEXT_PUBLIC_HACKATHON_ID,
12 | comment: comment,
13 | idea_id: idea_id,
14 | user_id: current_user,
15 | },
16 | return: ['id'],
17 | };
18 |
19 | return submit(input_obj);
20 | };
21 |
22 | export const like_idea = (idea_id, current_user) => {
23 | const input_obj = {
24 | display: 'Insert Comment',
25 | name: 'Insert_Hackathon_Idea_Likes_One',
26 | function: 'insert_hackathon_idea_likes_one',
27 | write: true,
28 | object: {
29 | hackathon_id: process.env.NEXT_PUBLIC_HACKATHON_ID,
30 | idea_id: idea_id,
31 | user_id: current_user,
32 | },
33 | return: ['id'],
34 | };
35 |
36 | return submit(input_obj);
37 | };
38 |
--------------------------------------------------------------------------------
/services/graphql/status.js:
--------------------------------------------------------------------------------
1 | import { submit } from '@/services/request';
2 | import * as _ from 'lodash';
3 |
4 | export const list_statuses = () => {
5 | const input_obj = {
6 | display: 'List Ideas',
7 | name: 'Hackathon_Status',
8 | function: 'hackathon_status',
9 | return: ['label', 'id'],
10 | };
11 | return submit(input_obj);
12 | };
13 |
14 | export const insert_ideas_status = (idea_object) => {
15 | const insert_obj = {
16 | display: 'Insert Idea Status',
17 | name: 'Insert_Hackathon_Idea_Status_one',
18 | function: 'insert_hackathon_idea_status_one',
19 | write: true,
20 | object: {
21 | idea_id: idea_object.id,
22 | status_id: idea_object.status,
23 | },
24 | return: ['id'],
25 | };
26 |
27 | return submit(insert_obj);
28 | };
29 |
30 | export const get_latest_status = (idea) => {
31 | const all_statuses = [];
32 |
33 | idea.idea_idea_status_map.forEach((st) => {
34 | all_statuses.push(st.idea_status_status_map);
35 | });
36 | const last_status = all_statuses[all_statuses.length - 1];
37 | return last_status;
38 | };
39 |
40 | export const get_idea_submission_info = (id) => {
41 | const input_obj = {
42 | display: 'List Ideas',
43 | name: 'Hackathon_Idea_submission',
44 | function: 'hackathon_idea_submission',
45 | where: {
46 | clause: {
47 | operator: 'and',
48 | conditions: [
49 | {
50 | field: 'idea_id',
51 | operator: 'eq',
52 | value: id,
53 | },
54 | ],
55 | },
56 | },
57 | return: ['application', 'blog_url', 'comment', 'repository_url'],
58 | };
59 | return submit(input_obj);
60 | };
61 |
--------------------------------------------------------------------------------
/services/metadata/hackrplay.js:
--------------------------------------------------------------------------------
1 | export const Config = {
2 | name: "hackrplay",
3 | display: "Hack-R-Play",
4 | completed: true,
5 | links: [
6 | {
7 | name: "About",
8 | href: "#about",
9 | },
10 | {
11 | name: "Sponsors",
12 | href: "#sponsors",
13 | },
14 | {
15 | name: "Judges",
16 | href: "#judges",
17 | },
18 | {
19 | name: "Faqs",
20 | href: "#faqs",
21 | },
22 | ],
23 | submissionurl: "hackrplay/ideas",
24 | subtitle:
25 | "ReactPlay brings you the opportunity to take part in the Hackathon and learn from it. Showcase your mindblowing ideas, build projects, and create content - there are also chances to win exciting prizes",
26 | about: {
27 | texts: [
28 | "Developers are lifetime hackers!",
29 | "Hack-R-Play is an initiative from the ReactPlay platform to help you hack, build, learn, and simultaneously contribute open source through #hacktoberfest",
30 | "All for it? Here are some rules you need to keep in mind:",
31 | ],
32 | bullets: [
33 | "It must be built in React Ecosystem. (eg - ReactJS, NextJS, RemixJS etc)",
34 | "The app must use one or more service of [Nhost backend](https://nhost.io)",
35 | "Project source code must be open on github.",
36 | "You must deploy the app publicly.",
37 | "You must write an article about your journey of building it and publish it on the ReactPlay blog.",
38 | "[Read more](https://blog.reactplay.io/announcing-hack-r-play-hackathon-from-react-play) on the ReactPlay repository for each pull request.",
39 | ],
40 | footer:
41 | "Please join the [ReactPlay discord server](https://discord.gg/UfYj4MvW9A) to get any help while you are building.",
42 | highlights: [
43 | "Create 2 Plays using React",
44 | "Share your journey publicly",
45 | "Get the plays reviewed and merged",
46 | ],
47 | },
48 | judges: [
49 | {
50 | name: "Johan Eliasson",
51 | twitter: "elitasson",
52 | title: "CEO Nhost",
53 | avatar:
54 | "https://pbs.twimg.com/profile_images/1447184004558557193/agXMdsqe_400x400.jpg",
55 | },
56 | {
57 | name: "Koustov Maitra",
58 | twitter: "koustov",
59 | title: "Solution Architect, ReactPlay",
60 | avatar:
61 | "https://pbs.twimg.com/profile_images/1443859238443360258/6_H-pDaM_400x400.jpg",
62 | },
63 | {
64 | name: "Pratim Bhosale",
65 | twitter: "BhosalePratim",
66 | title: "Developer Advocate, Nhost",
67 | avatar:
68 | "https://pbs.twimg.com/profile_images/1489130124792369154/-3M4AlrG_400x400.jpg",
69 | },
70 | {
71 | name: "Tapas Adhikary",
72 | twitter: "tapasAdhikary",
73 | title: "Founder, ReactPlay",
74 | avatar:
75 | "https://pbs.twimg.com/profile_images/1495457010598309888/zPrTNF4F_400x400.jpg",
76 | },
77 | ],
78 | faqs: [
79 | {
80 | question: "Why should I perticipate in the Hack-R-Play?",
81 | answer:
82 | "Do you like learning while building something? How about a platform that provides you with an opportunity to build a full-stack application end-to-end, showcase it to the world, motivate you to create content about it, and help build networking? Hack-R-Play aims precisely the same. Join the Hackathon brought to you by ReactPlay and start building a cool project that we can't wait to see!",
83 | },
84 | {
85 | question: "Do I need to Register for Hack-R-Play?",
86 | answer:
87 | "Yes, you need to Register your idea for the Hack-R-Play hackathon. To do that, click on the REGISTER button at the top of the page and submit a few details to register your idea.",
88 | },
89 | {
90 | question: "Can we participate as a team?",
91 | answer:
92 | "Yes, you can participate in a team of 2(max). You can select the other member's name when you register your idea for the event. If you are the only person registering for an idea, just skip selecting any member while registering. If you liked an idea and want be part of it, please contact the idea creator.",
93 | },
94 | {
95 | question: "Does my Idea needs to follow a specific theme?",
96 | answer:
97 | "Not really! However, we suggest you build something valuable that you will keep building even after the Hack-R-Play Event. Rest is entirely up to you.",
98 | },
99 | {
100 | question: "Can I use anything other than React?",
101 | answer:
102 | "You can use anything related to React and its ecosystem. You can use Next.js, Gatsby, React Native, and even plain React!",
103 | },
104 | {
105 | question: "What do I need to Submit?",
106 | answer:
107 | "When you submit the project after completion, you submit three public links. Link to your project source code, link to your application, and link to the article that explains how you have used React/React-based library/framework with Nhost to build this application.",
108 | },
109 | {
110 | question: "Is the blog article mandatory to submit?",
111 | answer:
112 | "Yes, very much! Please document your entire Hack-R-Play journey and publish them on the ReactPlay blog(blog.reactplay.io). Don't worry if you are not a seasoned blogger. We will help with reviews if you submit the blog article at least 3 days before the event's end date.",
113 | },
114 | {
115 | question: "When and How the Hack-R-Play result will be published?",
116 | answer:
117 | "Hack-R-Play 2022 results will be published on 30th October. We will publish it on our website, and the Twitter handle(@reactplayio).",
118 | },
119 | {
120 | question: "Do we get prizes?",
121 | answer:
122 | "Yes, we will select 3 best ideas to give the exciting prizes sponsored by Nhost.",
123 | },
124 | {
125 | question: "I have questions, where can I ask them?",
126 | answer:
127 | "Got a question? Please join our Discord(the link is in the footer of this page). You can ask us anything in the hack-r-play channel.",
128 | },
129 | ],
130 | cta: {
131 | title: "Be a part of the best react event",
132 | description:
133 | "Learning is a journey than a destination. We developers need avenues, motivations, and opportunities to keep going. Join the Hack-R-Play hackathon to experience it. It will allow you to build a full-stack app using React and Nhost. Why waiting? Register your idea today",
134 | },
135 | partners: [
136 | {
137 | logo: "NhostLogo.svg",
138 | text: "Nhost is the open source GraphQL backend (Firebase Alternative) and a development platform. Nhost is doing for the backend, what Netlify and Vercel are doing for the frontend. It make things easy to build and deploy this backend using our platform that takes care of configuration, security, and performance. Things just works andscale automatically so you can focus on your product and on your business.",
139 | display: "NHost",
140 | link: "https://docs.nhost.io/",
141 | },
142 | ],
143 | winners: [
144 | {
145 | name: "Chakri",
146 | twitter: "https://twitter.com/geekyChakri",
147 | github: "https://github.com/GeekyChakri",
148 | email: "geekychakri@gmail.com",
149 | avatar:
150 | "https://pbs.twimg.com/profile_images/1532395278107435011/jBTuAENH_400x400.png",
151 | projectName: "Classroom",
152 | projectLink: "https://learnwithclassroom.vercel.app",
153 | article:
154 | "https://blog.reactplay.io/introducing-classroom-learning-with-youtube-made-exciting",
155 | projectSource: "https://github.com/GeekyChakri/Classroom",
156 |
157 | position: "1",
158 | },
159 | {
160 | name: "Shyam Mahanta",
161 | twitter: "https://twitter.com/ShyamMahanta2",
162 | github: "https://github.com/Angryman18",
163 | email: "smahanta118@gmail.com",
164 | avatar: "https://avatars.githubusercontent.com/u/63530626?v=4",
165 | projectName: "Papercode",
166 | projectLink: "https://papercode.netlify.app/",
167 | projectSource: "https://github.com/Angryman18/papercode",
168 |
169 | article:
170 | "https://blog.reactplay.io/tour-of-a-live-coding-playground-app-built-using-reactjs-nhost",
171 | position: "2",
172 | },
173 | {
174 | name: "Aashish Panthi",
175 | twitter: "https://twitter.com/aashishpanthi11",
176 | github: "https://github.com/aashishpanthi",
177 | email: "aashishpanthi11@gmail.com",
178 | avatar: "https://avatars.githubusercontent.com/u/60884239?v=4",
179 | projectName: "Mailsbe",
180 | projectLink: "https://mailsbe.netlify.app/",
181 | projectSource: "https://github.com/aashishpanthi/mailsbe",
182 | article: "https://blog.reactplay.io/mailsbe-an-email-status-finder",
183 | position: "3",
184 | },
185 | ],
186 | mentions: [
187 | {
188 | name: "Supriya M",
189 | twitter: "https://twitter.com/supminn",
190 | github: "https://github.com/supminn",
191 | email: "sansup49@gmail.com",
192 | avatar: "https://avatars.githubusercontent.com/u/30731236?v=4",
193 | projectName: "FinSaver",
194 | projectLink: "https://finsaver.vercel.app/",
195 | projectSource: "https://github.com/supminn/expense_tracker",
196 |
197 | article: "https://blog.reactplay.io/building-finsaver-for-hack-r-play",
198 | },
199 | {
200 | name: "Armaan Kazi",
201 | twitter: "https://twitter.com/Armankazi111",
202 | github: "https://github.com/Amyx000/",
203 | email: "armankazi111@gmail.com",
204 | avatar: "https://avatars.githubusercontent.com/u/104687128?v=4",
205 | projectName: "React Resume Builder",
206 | projectLink: "https://react--resume--builder.vercel.app/",
207 | projectSource: "https://github.com/Amyx000/React-Resume-Builder",
208 |
209 | article:
210 | "https://blog.reactplay.io/react-resume-builder-with-react-and-nhost",
211 | },
212 | {
213 | name: "Ammaar Aslam",
214 | twitter: "https://twitter.com/itsammaar_7",
215 | github: "https://github.com/ammaaraslam",
216 | email: "ammaaraslam7@gmail.com",
217 | avatar:
218 | "https://avatars.githubusercontent.com/u/96367405?s=400&u=cb1c3999b75b33502f3149fd47b251731be286e7&v=4",
219 | projectName: "WriteOnce",
220 | projectLink: "https://writeonce.vercel.app/",
221 | projectSource: "https://github.com/ammaaraslam/write-once",
222 |
223 | article:
224 | "https://blog.reactplay.io/introducing-writeonce-a-markdown-editor-for-devs-who-blog",
225 | },
226 | ],
227 | };
228 |
--------------------------------------------------------------------------------
/services/metadata/index.js:
--------------------------------------------------------------------------------
1 | import { Config as tp_config } from './twoplaysamonth';
2 | import { Config as hrp_config } from './hackrplay';
3 |
4 | export const MetaConfigs = {
5 | twoplaysamonth: tp_config,
6 | hackrplay: hrp_config,
7 | };
8 |
--------------------------------------------------------------------------------
/services/metadata/twoplaysamonth.js:
--------------------------------------------------------------------------------
1 | export const Config = {
2 | name: "twoplaysamonth",
3 | display: "#2PlaysAMonth",
4 | description:
5 | "#2PlaysAMonth is an event by ReactPlay for the ReactJs community to learn, build, share in public. Join us.",
6 | keywords: "ReactPlay, #2PlaysAMonth, ReactJS",
7 | completed: false,
8 | started: false,
9 | links: [
10 | {
11 | name: "About",
12 | href: "#about",
13 | },
14 | {
15 | name: "Sponsors",
16 | href: "#sponsors",
17 | },
18 | {
19 | name: "Judges",
20 | href: "#judges",
21 | },
22 | {
23 | name: "Faqs",
24 | href: "#faqs",
25 | },
26 | ],
27 | result_links: [
28 | [
29 | {
30 | link: "https://reactplay.io/plays?tags=f86a69e3-6528-4761-b56c-19fa95960b09",
31 | name: "#2PlaysAMonth Plays",
32 | target: "_blank",
33 | type: "primary",
34 | },
35 | ],
36 | [
37 | {
38 | link: "https://github.com/reactplay/react-play/issues?q=is%3Aissue+label%3A%232PlaysAMonth+",
39 | name: "Ideas",
40 | target: "_blank",
41 | },
42 | {
43 | link: "https://github.com/reactplay/react-play/pulls?q=is%3Apr+label%3A%232PlaysAMonth+",
44 | name: "Submissions",
45 | target: "_blank",
46 | },
47 | ],
48 | ],
49 | subtitle:
50 | "ReactPlay brings you an opportunity to participate in the month-long drive to learn and contribute to Open Source. Join the #2PlaysAMonth and build two projects(plays) in the month of February. You will learn from expert code reviews while contributing to Open Source - you may also win some exciting prizes.",
51 | about: {
52 | texts: [
53 | "#2PlaysAMonth is an initiative from the ReactPlay community to help you learn, build, and simultaneously contribute to open source throughout the month of February.",
54 | "Would you be up for it? Here are a few things to keep in mind before you get started:",
55 | ],
56 | bullets: [
57 | "You must complete two plays(React Projects) in ReactPlay between February 1st to February 28th 2023.",
58 | "You must follow the [Create a Play](https://github.com/reactplay/react-play/blob/main/CREATE-PLAY.md) steps to create the play. Please [create an issue](https://github.com/reactplay/react-play/issues/new?assignees=&labels=%232PlaysAMonth&template=%232PlaysAMonth.yml&title=%5B%232PlaysAMonth%5D%3A+) on the ReactPlay repository for each pull request.",
59 | "Your play must have `#2PlaysAMonth` tag added to it while creating.",
60 | "You can build any play of your choice. If you are looking for ideas, [here are some you can get inspired by](https://reactplay.io/ideas).",
61 | "You must register on [stackstream](https://www.stack-stream.com/).",
62 | "Create a demo on [stackstream](https://www.stack-stream.com/) explaining your work and add the recording link to your play by editing it.",
63 | "Additionally, if you spend at least 5 hours streaming on [stackstream](https://www.stack-stream.com/) in the February month, you qualify for additional bonus points(karma) to win.",
64 | "Share a Tweet and/or LinkedIn Post announcing your participation and PR merge with the hashtag `#2PlaysAMonth` and tag ReactPlay's handle(@ReactPlayIO)",
65 | ],
66 | footer:
67 | "Please join the [ReactPlay discord server](https://discord.gg/UfYj4MvW9A) to get any help while you are building. Also, check the [FAQ](https://hustles.reactplay.io/events/23/twoplaysamonth#faqs) section for more details.",
68 | highlights: [
69 | "Complete 2 Plays using ReactJS",
70 | "Demo your work",
71 | "Win badges, prizes, and bonus points",
72 | ],
73 | },
74 | judges: [
75 | {
76 | name: "Harshit Jain",
77 | twitter: "jain_harshit",
78 | title: "SDE3, Intuit",
79 | avatar:
80 | "https://pbs.twimg.com/profile_images/1523150875153567744/zpRDym_L_400x400.jpg",
81 | },
82 | {
83 | name: "Kapeel Kokane",
84 | twitter: "kokaneka",
85 | title: "SDE2, Microsoft",
86 | avatar:
87 | "https://pbs.twimg.com/profile_images/1372919009939652612/E9s309tH_400x400.jpg",
88 | },
89 | {
90 | name: "Koustov Maitra",
91 | twitter: "koustov",
92 | title: "Architect, ReactPlay",
93 | avatar:
94 | "https://pbs.twimg.com/profile_images/1443859238443360258/6_H-pDaM_400x400.jpg",
95 | },
96 | {
97 | name: "Tapas Adhikary",
98 | twitter: "tapasAdhikary",
99 | title: "Founder, ReactPlay",
100 | avatar:
101 | "https://pbs.twimg.com/profile_images/1495457010598309888/zPrTNF4F_400x400.jpg",
102 | },
103 | ],
104 | faqs: [
105 | {
106 | question: "Why should I participate in the #2PlaysAMonth event?",
107 | answer:
108 | "Do you like learning while building something? How about a platform that allows you to build a ReactJS application end-to-end, learn from the review comments, contribute to open source, showcase it to the world, and help build networking? #2PlaysAMonth aims precisely the same. Join the drive brought to you by ReactPlay and start building cool projects that we can't wait to see!",
109 | },
110 | {
111 | question: "Do I need to Register for #2PlaysAMonth?",
112 | answer:
113 | "Nope. You can create the play by following the criteria mentioned in this page's About section.",
114 | },
115 | {
116 | question: "Is it mandatory to create 2 plays?",
117 | answer:
118 | "Yes. That's one of the qualifying criteria. You must create and complete 2 plays.",
119 | },
120 | {
121 | question: "What if my play review gets delayed?",
122 | answer:
123 | "You must ensure you give the reviewers enough time to review your code and provide comments. We're looking forward to 4-5 days(based on how actively you respond to the comments) to complete the review process of a play. Try submitting your plays at least 7-10 days before the end date to avoid messy situations. If your review gets delayed by reviewers, we will ensure you the extra time, but that will be a rare case!",
124 | },
125 | {
126 | question: "Can we participate as a team?",
127 | answer:
128 | "Nope. It's an individual event. However, feel free to collaborate with others.",
129 | },
130 | {
131 | question: "Can I use anything other than React?",
132 | answer:
133 | "ReactPlay is a platform to help web developers learn ReactJs and build projects. For this initiative, ReactJs is a must.",
134 | },
135 | {
136 | question: "Can I submit my old React project as a play?",
137 | answer:
138 | "You can. However, could you please mention the old project in the play description? Also, the play should be something other than a 1-1 matching your existing project. You must bring some changes/ideas into it.",
139 | },
140 | {
141 | question: "Can I submit code/project of someone else?",
142 | answer:
143 | "You shouldn't. Be authentic and ethical. It's an event to learn, not alone to win.",
144 | },
145 | {
146 | question: "Is creating an issue for my PR a must?",
147 | answer:
148 | "Yes. We will disqualify the play submission that doesn't have an associated issue.",
149 | },
150 | {
151 | question:
152 | "Is announcing my participation and progress on the social media a must?",
153 | answer:
154 | "No. However, we encourage you to build and learn publicly. Make sure you add the tag #2PlaysAMonth and ReactPlay handle when you post them on social media.",
155 | },
156 | {
157 | question: "Is recording a Demo of my work on stackstream a must?",
158 | answer:
159 | "Yes, we encourage you to share your work publicly and at the same time, get better at public speaking. Please register on stackstream and create your streams for free. Don't forget to add the stream recording link into the readme file of the related play.",
160 | },
161 | {
162 | question: "What about the 5 hours of streaming a month and bonus points?",
163 | answer:
164 | "There is a chance to win bonus points if you spend at least 5 hours streaming on stackstream in the February month. For each hour, you will get a bonus point(karma). You can use the stackstream platform for free in the entire duration of the #2PlaysAMonth challenge. You can collaborate, share your learnings, demo, etc. Based on your Karma points you got from your streaming and engagement , you can also win something (even if you couldn't finish your play). Top 3 highest karma point holder will get 3 exciting prizes from stackstream (the threshold is 100 karma points).",
165 | },
166 | {
167 | question: "When and How the #2PlaysAMonth result will be published?",
168 | answer:
169 | "The result will be published on 15th March. We will publish it on our website, blog, and Twitter handle(@reactplayio).",
170 | },
171 | {
172 | question: "Do I get badges and prizes?",
173 | answer:
174 | "We will publish 3 winners and 3 special mentions based on our judging criteria. All winners, special mentions, and participants who completed the target will receive digital badges. We are working with our sponsors to decide the prizes for the winners.",
175 | },
176 | {
177 | question: "I have questions, where can I ask them?",
178 | answer:
179 | "Got a question? Please join our Discord(the link is in the footer of this page). You can ask us anything in the #2PlaysAMonth channel.",
180 | },
181 | ],
182 | cta: {
183 | title: "Be a part of the best react event",
184 | description:
185 | "Learning is a journey than a destination. We, developers, need avenues, motivations, and opportunities to keep going. Join the #2PlaysAMonth initiative to experience it. It will allow you to build a ReactJS app using and learning from code reviews. Why waiting? Get started today.",
186 | },
187 | partners: [
188 | {
189 | image: "PartnersPolygon.svg",
190 | text: "Grow your developer community. From now on, your community members never code alone.",
191 | display: "stackstream",
192 | link: "https://www.stack-stream.com/",
193 | },
194 | ],
195 | };
196 |
197 | export default Config;
198 |
--------------------------------------------------------------------------------
/services/nhost/index.js:
--------------------------------------------------------------------------------
1 | const AUTH_URL = (redirectURL, provider = "github") => {
2 | const BACKEND_URL = `${process.env.NEXT_PUBLIC_NHOST_BACKEND_URL}/${process.env.NEXT_PUBLIC_NHOST_VERSION}`;
3 | return `${BACKEND_URL}/auth/signin/provider/${provider}?redirectTo=${encodeURI(
4 | redirectURL
5 | )}`;
6 | };
7 |
8 | export const NHOST = { AUTH_URL };
9 |
--------------------------------------------------------------------------------
/services/request/index.js:
--------------------------------------------------------------------------------
1 | import {
2 | submit as gsubmit,
3 | submit_multi as gsubmit_multi,
4 | } from "json-graphql-parser/v2/index.js";
5 |
6 | const BACKEND_URL = `${process.env.NEXT_PUBLIC_NHOST_BACKEND_URL}/${process.env.NEXT_PUBLIC_NHOST_VERSION}/${process.env.NEXT_PUBLIC_NHOST_ENDPOINT}`;
7 |
8 | /**
9 | * Run GraphQL queries using Axios using multiple JSON object
10 | * @param {object[]} requests Mandatory.
11 | * @param {string} url Optional.
12 | * @param {object} reqheder Optional.
13 | */
14 | export const submit_multi = (requests, url, reqheder) => {
15 | return gsubmit_multi(requests, BACKEND_URL);
16 | };
17 |
18 | /**
19 | * Run GraphQL queries using Axios using a simple JSON object
20 | * @param {object} request Mandatory.
21 | * @param {string} url Optional.
22 | * @param {object} reqheder Optional.
23 | * @returns {Promise} single promise
24 | */
25 | export const submit = (request, url, reqheder) => {
26 | return gsubmit(request, BACKEND_URL);
27 | };
28 |
29 | export const submitMutation = (query, object) => {
30 | const mutationQuery = query;
31 | mutationQuery.object = object;
32 | return submit(mutationQuery);
33 | };
34 |
--------------------------------------------------------------------------------
/services/util/string.js:
--------------------------------------------------------------------------------
1 | const NEW_LINE_CHAR = '\n';
2 | const NEW_LINE_TEMPLATE = '_HP__10_NEW_LINE_10__HP_';
3 | export const escape_new_line = (source_str) => {
4 | if (!source_str) {
5 | return '';
6 | }
7 | const res = source_str.replace(
8 | new RegExp(NEW_LINE_CHAR, 'g'),
9 | NEW_LINE_TEMPLATE
10 | );
11 | return res;
12 | };
13 |
14 | export const unescape_new_line = (source_str) => {
15 | if (!source_str) {
16 | return '';
17 | }
18 | const res = source_str.replace(
19 | new RegExp(NEW_LINE_TEMPLATE, 'g'),
20 | NEW_LINE_CHAR
21 | );
22 | return res;
23 | };
24 |
--------------------------------------------------------------------------------
/services/util/time.js:
--------------------------------------------------------------------------------
1 | export const time_since = (date) => {
2 | var seconds = Math.floor((new Date() - date) / 1000);
3 |
4 | var interval = seconds / 31536000;
5 |
6 | if (interval > 1) {
7 | return Math.floor(interval) + ' years';
8 | }
9 | interval = seconds / 2592000;
10 | if (interval > 1) {
11 | return Math.floor(interval) + ' months';
12 | }
13 | interval = seconds / 86400;
14 | if (interval > 1) {
15 | return Math.floor(interval) + ' days';
16 | }
17 | interval = seconds / 3600;
18 | if (interval > 1) {
19 | return Math.floor(interval) + ' hours';
20 | }
21 | interval = seconds / 60;
22 | if (interval > 1) {
23 | return Math.floor(interval) + ' minutes';
24 | }
25 | return Math.floor(seconds) + ' seconds';
26 | };
27 |
--------------------------------------------------------------------------------
/styles/Common-component.module.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/styles/Common-component.module.css
--------------------------------------------------------------------------------
/styles/Home.module.css:
--------------------------------------------------------------------------------
1 | @import "form-control.css";
2 | .container {
3 | padding: 0 2rem;
4 | }
5 |
6 | .main {
7 | min-height: 100vh;
8 | padding: 4rem 0;
9 | flex: 1;
10 | display: flex;
11 | flex-direction: column;
12 | justify-content: center;
13 | align-items: center;
14 | }
15 |
16 | .footer {
17 | display: flex;
18 | flex: 1;
19 | padding: 2rem 0;
20 | border-top: 1px solid #eaeaea;
21 | justify-content: center;
22 | align-items: center;
23 | }
24 |
25 | .footer a {
26 | display: flex;
27 | justify-content: center;
28 | align-items: center;
29 | flex-grow: 1;
30 | }
31 |
32 | .title a {
33 | color: #0070f3;
34 | text-decoration: none;
35 | }
36 |
37 | .title a:hover,
38 | .title a:focus,
39 | .title a:active {
40 | text-decoration: underline;
41 | }
42 |
43 | .title {
44 | margin: 0;
45 | line-height: 1.15;
46 | font-size: 4rem;
47 | }
48 |
49 | .title,
50 | .description {
51 | text-align: center;
52 | }
53 |
54 | .description {
55 | margin: 4rem 0;
56 | line-height: 1.5;
57 | font-size: 1.5rem;
58 | }
59 |
60 | .code {
61 | background: #fafafa;
62 | border-radius: 5px;
63 | padding: 0.75rem;
64 | font-size: 1.1rem;
65 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
66 | Bitstream Vera Sans Mono, Courier New, monospace;
67 | }
68 |
69 | .grid {
70 | display: flex;
71 | align-items: center;
72 | justify-content: center;
73 | flex-wrap: wrap;
74 | max-width: 800px;
75 | }
76 |
77 | .card {
78 | margin: 1rem;
79 | padding: 1.5rem;
80 | text-align: left;
81 | color: inherit;
82 | text-decoration: none;
83 | border: 1px solid #eaeaea;
84 | border-radius: 10px;
85 | transition: color 0.15s ease, border-color 0.15s ease;
86 | max-width: 300px;
87 | }
88 |
89 | .card:hover,
90 | .card:focus,
91 | .card:active {
92 | color: #0070f3;
93 | border-color: #0070f3;
94 | }
95 |
96 | .card h2 {
97 | margin: 0 0 1rem 0;
98 | font-size: 1.5rem;
99 | }
100 |
101 | .card p {
102 | margin: 0;
103 | font-size: 1.25rem;
104 | line-height: 1.5;
105 | }
106 |
107 | .logo {
108 | height: 1em;
109 | margin-left: 0.5rem;
110 | }
111 |
112 | @media (max-width: 600px) {
113 | .grid {
114 | width: 100%;
115 | flex-direction: column;
116 | }
117 | }
118 |
119 | @media (prefers-color-scheme: dark) {
120 | .card,
121 | .footer {
122 | border-color: #222;
123 | }
124 | .code {
125 | background: #111;
126 | }
127 | .logo img {
128 | filter: invert(1);
129 | }
130 | }
131 |
132 | .text-title,
133 | .page-title {
134 | text-decoration: none;
135 | position: relative;
136 | }
137 |
138 | .text-title:after,
139 | .page-title:after {
140 | position: absolute;
141 | content: '';
142 | height: 4px;
143 | bottom: -8px;
144 |
145 | margin: 0 auto;
146 | left: 0;
147 | right: 0;
148 | width: 40%;
149 | background: transparent linear-gradient(90deg, #00F2FE 0%, #68FDC6 100%) 0% 0% no-repeat padding-box;
150 |
151 | -o-transition:.5s;
152 | -ms-transition:.5s;
153 | -moz-transition:.5s;
154 | -webkit-transition:.5s;
155 | transition:.5s;
156 | }
157 |
158 | .text-title:after{
159 | width: 100%;
160 | }
161 |
--------------------------------------------------------------------------------
/styles/form-control.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/reactplay/activities/d5bb8365d5e4099718c7331dc51cd29bd31480e3/styles/form-control.css
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap");
2 | @import url("https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap");
3 |
4 | @tailwind base;
5 | @tailwind components;
6 | @tailwind utilities;
7 |
8 | html,
9 | body {
10 | height: 100%;
11 | display: grid;
12 | scroll-behavior: smooth;
13 | }
14 |
15 | #__next {
16 | height: 100%;
17 | grid-row: 1/-1;
18 | grid-column: 1/-1;
19 | }
20 |
21 |
22 |
23 | [data-theme="hackrplay"] {
24 | --color-brand-bg: #051630;
25 | --color-brand-highlight: #00F2FE;
26 | --color-brand-primary-highlight: #4831D4;
27 | --color-brand-white: #FFFFFF
28 | }
29 |
30 | [data-theme="twoplaysamonth"] {
31 | --color-brand-bg: #1D1455;
32 | --color-brand-highlight: #CCF381;
33 | --color-brand-primary-highlight: #684EFF;
34 | --color-brand-white: #FFFFFF
35 | }
36 |
--------------------------------------------------------------------------------
/styles/idea.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | background-color: #ffffff;
3 | width: 100%;
4 | height: 100vh;
5 | padding: 1rem;
6 | }
7 |
8 | .pageTitle {
9 | font-family: Bebas Neue !important;
10 | }
11 |
12 | .card {
13 | width: 100%;
14 | height: 320px;
15 | background: #ffffff0f 0% 0% no-repeat padding-box !important;
16 | border: 2px solid #ffffff29 !important;
17 | border-radius: 64px 8px 8px 8px !important;
18 | opacity: 1;
19 | cursor: pointer;
20 | }
21 | .card:hover {
22 | border: solid 2px rgba(104, 253, 198, 1) !important;
23 | -webkit-box-shadow: 0px 0px 16px 1px rgba(104, 253, 198, 0.4);
24 | -moz-box-shadow: 0px 0px 16px 1px rgba(104, 253, 198, 0.4);
25 | box-shadow: 0px 0px 16px 1px rgba(104, 253, 198, 0.4);
26 | }
27 |
28 | .title {
29 | display: -webkit-box;
30 | -webkit-line-clamp: 2;
31 | -webkit-box-orient: vertical;
32 | overflow: hidden;
33 | line-clamp: 2;
34 | font-family: Bebas Neue !important;
35 | }
36 |
37 | .cardDescription {
38 | color: #ffffff99 !important;
39 | display: -webkit-box;
40 | -webkit-line-clamp: 4;
41 | -webkit-box-orient: vertical;
42 | overflow: hidden;
43 | line-clamp: 4;
44 | font-family: Roboto Mono !important;
45 | }
46 |
47 | .cardAvatar {
48 | border-radius: 50%;
49 | border: 2px solid #707070 !important;
50 | }
51 |
52 | .cardParent {
53 | position: absolute;
54 | top: 0.09rem;
55 | left: 2rem;
56 | width: 50px;
57 | }
58 |
59 | .cardStatus {
60 | font-family: Roboto Mono, Regular !important;
61 | }
62 |
63 | .registerBtn {
64 | width: 150px;
65 | padding: 0.5rem;
66 | height: 44px;
67 | background: transparent
68 | linear-gradient(
69 | 146deg,
70 | var(--unnamed-color-00f2fe) 0%,
71 | #32f9e5 52%,
72 | var(--unnamed-color-68fdc6) 100%
73 | )
74 | 0% 0% no-repeat padding-box;
75 | background: transparent
76 | linear-gradient(146deg, #00f2fe 0%, #32f9e5 52%, #68fdc6 100%) 0% 0%
77 | no-repeat padding-box;
78 | border-radius: 2px;
79 | opacity: 1;
80 | }
81 |
82 | .underLine {
83 | height: 4px;
84 | background: transparent linear-gradient(90deg, #00f2fe 0%, #68fdc6 100%) 0% 0%
85 | no-repeat padding-box;
86 | opacity: 1;
87 | }
88 |
89 |
90 | /* Status Bar */
91 |
92 |
93 | .history-tl-container{
94 | display:block;
95 | position:relative;
96 | }
97 | .history-tl-container .tl{
98 | padding:0;
99 | display:inline-block;
100 |
101 | }
102 | .history-tl-container .tl .tl-item{
103 | list-style: none;
104 | margin:auto;
105 | min-height:50px;
106 | border-left:1px dashed #86D6FF;
107 | padding:0 0 50px 30px;
108 | position:relative;
109 | }
110 | .history-tl-container .tl li:last-child{ border-left:0; padding-bottom: 0px;}
111 | .history-tl-container .tl li::before{
112 | position: absolute;
113 | left: -12px;
114 | top: 5px;
115 | content: " ";
116 | border: 4px solid rgba(255, 255, 255, 0.84);
117 | border-radius: 500%;
118 | background: #258CC7;
119 | height: 25px;
120 | width: 25px;
121 | transition: all 500ms ease-in-out;
122 |
123 | }
124 | .tl .tl-item .item-title{
125 | }
126 | .tl .tl-item .item-detail{
127 | font-size:12px;
128 | }
129 | .tl .tl-item .timestamp{
130 | color: #8D8D8D;
131 | position: absolute;
132 | width:100px;
133 | left: -50%;
134 | text-align: right;
135 | font-size: 12px;
136 | }
137 |
138 | /* Comment */
139 |
140 | .arrow-box{
141 | position: relative;
142 | width:220px;
143 | background: #fff;
144 | height:100px;
145 | line-height: 40px;
146 | margin-bottom:30px;
147 | text-align:center;
148 | color:#fff;
149 | padding: 8px
150 | }
151 | .arrow-left:before{
152 | content: "";
153 | position: absolute;
154 | left: -20px;
155 | top: 0;
156 | border-top: 20px solid transparent;
157 | border-bottom: 20px solid transparent;
158 | border-right: 20px solid #fff;
159 | }
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | const plugin = require("tailwindcss/plugin");
3 | module.exports = {
4 | darkMode: false,
5 | content: [
6 | "./pages/**/*.{js,ts,jsx,tsx}",
7 | "./components/**/*.{js,ts,jsx,tsx}",
8 | ],
9 | theme: {
10 | fontFamily: {
11 | primary: ["Bebas Neue", "cursive"],
12 | body: ["Roboto Mono", "monospace"],
13 | },
14 | letterSpacing: {
15 | wild: "0.3rem",
16 | },
17 | extend: {
18 | colors: {
19 | "brand-hightlight": "#32f9e5",
20 | "brand-title": "#00F2FE",
21 | "brand-muted": "#ffffff99",
22 | "brand-bg": "var(--color-brand-bg)",
23 | "brand-white": "var(--color-brand-white)",
24 | "brand-highlight": "var(--color-brand-highlight)",
25 | "brand-primary-highlight": "var(--color-brand-primary-highlight)",
26 | },
27 | keyframes: {
28 | shimmer: {
29 | "100%": {
30 | transform: "translateX(100%)",
31 | },
32 | },
33 | },
34 |
35 | shadow: {
36 | simple: "0px 0px 16px 1px rgba(104, 253, 198, 0.4)",
37 | },
38 | },
39 | },
40 |
41 | plugins: [
42 | plugin(({ addVariant }) => {
43 | addVariant("selected", '&[selected="1"]');
44 | }),
45 | ],
46 | };
47 |
--------------------------------------------------------------------------------