├── .env.example ├── .gitignore ├── .vscode └── settings.json ├── README.md ├── components ├── club │ ├── card.js │ ├── gallery.js │ ├── hero.js │ ├── index.js │ ├── socials.js │ ├── stats.js │ └── team.js ├── github.js ├── hero.js ├── index.js ├── intro.js ├── leaderboard.js ├── meta.js ├── nav.js └── search.js ├── lib ├── css │ └── tippy.css ├── data.js ├── firebase │ ├── add.js │ ├── add_club.js │ ├── add_team.js │ ├── data.js │ ├── firebase.js │ ├── get_all_clubs.js │ ├── get_all_paths.js │ ├── get_club_data.js │ ├── get_posts_data.js │ ├── get_team_data.js │ ├── index.js │ └── script.js ├── theme │ └── index.js └── utils │ ├── get_slack_username.js │ ├── index.js │ └── scrapbook_exists.js ├── next.config.js ├── package.json ├── pages ├── _app.js ├── api │ └── hello.js ├── club │ └── [slug].js └── index.js ├── public ├── flag.png ├── hc_logo.png ├── profile_pic.png └── profile_pic2.jpeg └── yarn.lock /.env.example: -------------------------------------------------------------------------------- 1 | apiKey="YOUR_API_KEY(firebase)" 2 | authDomain="AUTH_DOMAIN(firebase)" 3 | projectId="AUTH_PROJECT_ID(firebase)" 4 | storageBucket="STORAGE_BUCKET(firebase)" 5 | messagingSenderId="MESSAGE_SENDER_ID(firebase)" 6 | appId="APP_ID(firebase)" 7 | measurementId="MEASUREMENT_ID(firebase)" 8 | OAUTH_TOKEN="YOUR_SLACK_OAUTH_TOKEN" 9 | PROD="true/false" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # vercel 35 | .vercel 36 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "activityBar.activeBackground": "#1a1a1a", 4 | "activityBar.activeBorder": "#606020", 5 | "activityBar.background": "#1a1a1a", 6 | "activityBar.foreground": "#e7e7e7", 7 | "activityBar.inactiveForeground": "#e7e7e799", 8 | "activityBarBadge.background": "#606020", 9 | "activityBarBadge.foreground": "#e7e7e7", 10 | "statusBar.background": "#000000", 11 | "statusBar.foreground": "#e7e7e7", 12 | "statusBarItem.hoverBackground": "#1a1a1a", 13 | "titleBar.activeBackground": "#000000", 14 | "titleBar.activeForeground": "#e7e7e7", 15 | "titleBar.inactiveBackground": "#00000099", 16 | "titleBar.inactiveForeground": "#e7e7e799" 17 | }, 18 | "peacock.color": "#000000" 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Directory 4 | 5 | Welcome to Hack Club APAC Directory, a Directory like never before 🚀 6 | This is the frontend of the Directory, deployed at [https://apacdirectory.hackclub.com](apacdirectory.hackclub.com). 7 | 8 | ## Docs/Guide 9 | 10 | To know the project better, please read the documentation from [here.](https://app.gitbook.com/@bajpaiharsh244/s/apac-directory) 11 | 12 | image 13 | 14 | ## The Saga 15 | 16 | The Directory acts as a place to explore Hack Clubs in the APAC region and explore the amazing work being done by them in the Hack Club circle. 17 | 18 | ![Directory image](https://cloud-82lkrqpe8-hack-club-bot.vercel.app/0image.png) 19 | 20 | The Directory is a real-time platform where hack clubs are given: 21 | 22 | 1. a digital profile to show amazing people and work happening at their hack club. 23 | 2. a platform to discover other amazing hack clubs in their region. 24 | 3. a platform to maintain stats for their Hack Club. 25 | 4. a complete slack environment to manage their club's presence on the Directory. 26 | 27 |
28 | These are the stats that are provided for every Hack Club's page of the Directory. 29 | 30 | | Column 1 | 31 | | :----------- | 32 | | `ship` | 33 | | `meetings` | 34 | | `events` | 35 | | `hackathons` | 36 | 37 | ## Club Pages 38 | 39 | Each hack club on the Directory has its own unique club page. 40 | 41 | ![image](https://raw.githubusercontent.com/bajpai244/indiablogfilehosting/main/files/ss1.png) 42 | 43 | The club page contains the following things: 44 | 45 | 1. cover image 46 | 2. club's description 47 | 3. club's logo 48 | 4. club's stats 49 | 5. club's members 50 | 6. club's wall 51 | 52 | ![image](https://raw.githubusercontent.com/bajpai244/indiablogfilehosting/main/files/details.png) 53 | 54 | > Everything mentioned above is customizable via a bot [ranker](https://github.com/hackclub/ranker) that we have integrated into Hack Club's Slack. 55 | > So Hack Clubs have full control over their club's page without the requirement of any middlemen. 56 | 57 | ## Club Wall 58 | 59 | Each club page has a club wall, which contains images and videos from a club's events, meets, and other activities. 60 | ![image](https://raw.githubusercontent.com/bajpai244/indiablogfilehosting/main/files/wall.png) 61 | 62 | ## Meet our Developer Team 63 | 64 | > This project required a very big force of software developers let's meet them! 65 | 66 | ![image](https://raw.githubusercontent.com/bajpai244/indiablogfilehosting/main/files/dev_army.png) 67 | 68 | ## Why star this repo 69 | 70 | > Why should you star this repo, let's see ...👀 71 | 72 | ![image](https://raw.githubusercontent.com/bajpai244/indiablogfilehosting/main/files/start_repo.png) 73 | 74 | > Anway if you like this project then that already makes me happy, keep hacking and keep the hacker spirit alive. 75 | -------------------------------------------------------------------------------- /components/club/card.js: -------------------------------------------------------------------------------- 1 | /**@jsxImportSource theme-ui */ 2 | 3 | import { Box, Flex } from "theme-ui"; 4 | import ReactPlayer from "react-player"; 5 | 6 | const Component = ({ text, video_url = undefined, video_poster, img_url }) => { 7 | return ( 8 | 27 | {video_url ? ( 28 | 36 | ) : ( 37 |

{text}

38 | )} 39 | 40 | {img_url ? ( 41 | 45 | ) : null} 46 |
47 | ); 48 | }; 49 | 50 | export default Component; 51 | -------------------------------------------------------------------------------- /components/club/gallery.js: -------------------------------------------------------------------------------- 1 | /*@jsxImportSource theme-ui*/ 2 | 3 | import Masonry from "react-masonry-css"; 4 | 5 | import Card from "./card"; 6 | 7 | const Component = ({ posts_data }) => ( 8 | <> 9 | 22 | {posts_data.map(({ ...props }) => ( 23 | 24 | ))} 25 | 26 | 62 | 63 | ); 64 | 65 | export default Component; 66 | -------------------------------------------------------------------------------- /components/club/hero.js: -------------------------------------------------------------------------------- 1 | /**@jsxImportSource theme-ui*/ 2 | 3 | import { Box, Container, Flex } from "theme-ui"; 4 | import Image from "next/image"; 5 | 6 | import hc_logo_src from "../../public/hc_logo.png"; 7 | 8 | const Hero = ({ cover, desc, logo, children, ...props }) => { 9 | return ( 10 | 23 | {children} 24 | 25 | 26 | 27 | ); 28 | }; 29 | 30 | const Notification = ({ desc, ...props }) => { 31 | return ( 32 | 48 |

{desc}

49 |
50 | ); 51 | }; 52 | 53 | const Club_Logo = ({ logo, ...props }) => { 54 | return ( 55 | 70 | hack club cgc's logo 79 | 80 | ); 81 | }; 82 | 83 | export default Hero; 84 | -------------------------------------------------------------------------------- /components/club/index.js: -------------------------------------------------------------------------------- 1 | export { default as Hero } from "./hero.js"; 2 | export { default as Stats } from "./stats"; 3 | export { default as Team } from "./team"; 4 | export { default as Gallery } from "./gallery"; 5 | export { default as Socials } from "./socials"; 6 | -------------------------------------------------------------------------------- /components/club/socials.js: -------------------------------------------------------------------------------- 1 | /**@jsxImportSource theme-ui*/ 2 | 3 | import { Box, Flex } from "theme-ui"; 4 | 5 | const Socials = ({ 6 | twitter, 7 | linkedin, 8 | instagram, 9 | github, 10 | website, 11 | ...props 12 | }) => { 13 | const social_props = { twitter, github, website, instagram, linkedin }; 14 | 15 | return ( 16 | 23 | {create_list(social_props).map(({ img_url, href }, idx) => ( 24 | 25 | ))} 26 | 27 | ); 28 | }; 29 | 30 | const Icon = ({ img_url, ...props }) => { 31 | return ( 32 | 33 | icon 41 | 42 | ); 43 | }; 44 | 45 | const create_list = (social_props) => { 46 | const keys = Object.keys(social_props).filter((key) => social_props[key]); 47 | 48 | return keys.map((key) => ({ img_url: data[key], href: social_props[key] })); 49 | }; 50 | 51 | const data = { 52 | twitter: 53 | "https://cloud-aupp4896s-hack-club-bot.vercel.app/0icons8-twitter-circled-144.png", 54 | website: 55 | "https://cloud-6vlxfvh8y-hack-club-bot.vercel.app/0icons8-website-96.png", 56 | linkedin: 57 | "https://cloud-14xsvnowt-hack-club-bot.vercel.app/3icons8-linkedin-144.png", 58 | instagram: 59 | "https://cloud-14xsvnowt-hack-club-bot.vercel.app/2icons8-instagram-logo-144.png", 60 | github: 61 | "https://cloud-14xsvnowt-hack-club-bot.vercel.app/0icons8-github-144.png", 62 | }; 63 | 64 | export default Socials; 65 | -------------------------------------------------------------------------------- /components/club/stats.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | * @jsxImportSource theme-ui 4 | */ 5 | 6 | import { Box, Container, Flex, Grid } from 'theme-ui'; 7 | import { HelpCircle } from 'react-feather'; 8 | import Tippy from '@tippyjs/react'; 9 | import Socials from './socials'; 10 | 11 | const Stats = ({ 12 | name, 13 | ships, 14 | hackathons, 15 | meetings, 16 | events, 17 | points, 18 | t_points, 19 | twitter, 20 | linkedin, 21 | instagram, 22 | github, 23 | website, 24 | ...props 25 | }) => { 26 | return ( 27 | 28 |

41 | {name} 42 |

43 | 44 | 45 | 46 | 52 |
53 | ); 54 | }; 55 | 56 | const Stats_Bar = ({ 57 | ships, 58 | meetings, 59 | hackathons, 60 | events, 61 | points, 62 | t_points, 63 | ...props 64 | }) => { 65 | const data = [ 66 | { attribute: 'ships', value: ships }, 67 | { attribute: 'meetings', value: meetings }, 68 | { attribute: 'hackathons', value: hackathons }, 69 | { attribute: 'events', value: events }, 70 | ]; 71 | 72 | return ( 73 | 81 | {data.map(({ ...props }) => ( 82 | 83 | ))} 84 | 85 | ); 86 | }; 87 | 88 | const Stat_Element = ({ attribute, value, label_element, ...props }) => { 89 | return ( 90 | 91 | 92 |

{attribute}

93 | {label_element} 94 |
95 |

{value}

96 |
97 | ); 98 | }; 99 | 100 | const TippyContainer = ({ children, content, ...props }) => ( 101 | 102 | {children} 103 | 104 | ); 105 | 106 | const Help_Comp = ({ ...props }) => { 107 | return ( 108 | 109 | 127 | 128 | ); 129 | }; 130 | 131 | const data = [ 132 | { 133 | attribute: 'ships', 134 | value: '30', 135 | }, 136 | { 137 | attribute: 'hackathons', 138 | value: '12', 139 | }, 140 | { 141 | attribute: 'meetings', 142 | value: '42', 143 | }, 144 | { 145 | attribute: 'events', 146 | value: '24', 147 | }, 148 | { 149 | attribute: 'points', 150 | value: '108', 151 | }, 152 | { 153 | attribute: 't.points', 154 | value: '600', 155 | }, 156 | ]; 157 | 158 | export default Stats; 159 | -------------------------------------------------------------------------------- /components/club/team.js: -------------------------------------------------------------------------------- 1 | /**@jsxImportSource theme-ui*/ 2 | 3 | import { Box, Container, Grid } from "theme-ui"; 4 | import Image from "next/image"; 5 | 6 | import img_1_src from "../../public/profile_pic.png"; 7 | import img_2_src from "../../public/profile_pic2.jpeg"; 8 | 9 | const Team = ({ team_data, ...props }) => { 10 | 11 | return ( 12 | 13 |

meet the team!

14 | 15 | 16 | 17 | {team_data.map(({ ...props }, idx) => { 18 | return ; 19 | })} 20 | 21 |
22 | ); 23 | }; 24 | 25 | const Member = ({ scrapbook_url, img_url, name, role, idx, ...props }) => { 26 | return ( 27 | 28 | 29 | member profile pic 42 |

{name}

43 |

44 | {role} 45 |

46 |
47 |
48 | ); 49 | 50 | }; 51 | 52 | export default Team; 53 | -------------------------------------------------------------------------------- /components/github.js: -------------------------------------------------------------------------------- 1 | /**@jsxImportSource theme-ui*/ 2 | 3 | import { Image } from "theme-ui"; 4 | 5 | // Github Logo 6 | 7 | const Github = () => { 8 | return ( 9 | github logo 27 | ); 28 | }; 29 | 30 | export default Github; 31 | -------------------------------------------------------------------------------- /components/hero.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | * @jsxImportSource theme-ui 4 | */ 5 | 6 | import { Box, Container, Heading } from 'theme-ui'; 7 | 8 | const Hero = ({ children, ...props }) => { 9 | return ( 10 | 21 | {children} 22 | 23 | Hack Club APAC 24 | 25 | 37 | Directory 38 | 39 | 40 | 41 | ); 42 | }; 43 | 44 | export default Hero; 45 | -------------------------------------------------------------------------------- /components/index.js: -------------------------------------------------------------------------------- 1 | export { default as Nav } from "./nav"; 2 | export { default as Hero } from "./hero"; 3 | export { default as Intro } from "./intro"; 4 | export { default as Search } from "./search"; 5 | export { default as Leaderboard } from "./leaderboard"; 6 | export { default as Meta } from "./meta"; 7 | export { default as Github } from "./github"; 8 | -------------------------------------------------------------------------------- /components/intro.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | * @jsxImportSource theme-ui 4 | */ 5 | 6 | import { Container, Heading, Text } from 'theme-ui'; 7 | 8 | const Intro = ({ ...props }) => { 9 | return ( 10 | 11 | may the force be with you 12 | 13 | Welcome 14 | 15 |

16 | The directory is a listing of Hack Clubs in the APAC region, click on a 17 | Hack Club to explore more about them! 18 |

19 |
20 | ); 21 | }; 22 | 23 | export default Intro; 24 | -------------------------------------------------------------------------------- /components/leaderboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | * @jsxImportSource theme-ui 4 | */ 5 | 6 | import { Container, Box, Grid, Button } from 'theme-ui'; 7 | import Link from 'next/link'; 8 | import { findIndex } from 'ramda'; 9 | 10 | const find_rank = (obj, dictionary) => { 11 | let rank = -1; 12 | 13 | dictionary.forEach(({ name }, idx) => { 14 | if (name === obj.name) rank = idx + 1; 15 | }); 16 | return rank; 17 | }; 18 | 19 | const Leaderboard = ({ data, original_data, ...props }) => { 20 | return ( 21 | 28 | 29 | {data.map(({ ...props }, index) => { 30 | return ( 31 | 36 | ); 37 | })} 38 | 39 | 40 | ); 41 | }; 42 | 43 | const Card = ({ name, points, logo, path, ...props }) => { 44 | return ( 45 | 46 | 71 |

72 | {name} {' '} 73 |

74 | 84 |
85 | 86 |
87 |
88 | 89 | ); 90 | }; 91 | 92 | export default Leaderboard; 93 | -------------------------------------------------------------------------------- /components/meta.js: -------------------------------------------------------------------------------- 1 | /** @format */ 2 | 3 | import React from 'react'; 4 | import Head from 'next/head'; 5 | 6 | const makeTitle = (title, name) => 7 | title === name ? title : `${title} – ${name}`; 8 | 9 | const site_description = 10 | 'The directory is a listing of Hack Clubs in the APAC region, click on a Hack Club to explore more about them!'; 11 | const site_keywords = 'directory,hack club,hack club directory,club profiles'; 12 | const site_og_img = 13 | 'https://cloud-kut3a9gjm-hack-club-bot.vercel.app/0image.png'; 14 | 15 | const Meta = ({ 16 | as: ElementType = Head, 17 | name = 'Hack Club', // site name 18 | title = 'Directory', // page title 19 | description = site_description, 20 | image = site_og_img, 21 | color = '#ec3750', 22 | manifest = 'https://assets.hackclub.com/favicons/site.webmanifest', 23 | children, 24 | }) => ( 25 | 26 | 27 | 28 | 29 | 30 | {makeTitle(title, name)} 31 | 32 | 37 | 38 | {description && ( 39 | 40 | 41 | 42 | 43 | 44 | )} 45 | {image && ( 46 | 47 | 48 | 49 | 50 | 51 | )} 52 | 53 | 54 | 60 | 66 | 73 | 80 | {manifest && } 81 | {children} 82 | 83 | ); 84 | 85 | export default Meta; 86 | -------------------------------------------------------------------------------- /components/nav.js: -------------------------------------------------------------------------------- 1 | /**@jsxImportSource theme-ui*/ 2 | 3 | import Image from "next/image"; 4 | import { Container, Button, Box, Link } from "theme-ui"; 5 | 6 | import flag_src from "../public/flag.png"; 7 | 8 | const Nav = ({ ...props }) => { 9 | return ( 10 | <> 11 | 12 | APAC Directory is being phased out in favour of Scrapbook. Join #scrapbook on {" "} 13 | the Hack Club Slack {" "} 14 | to get started or reach out for more details. 15 | 16 | 17 | 18 | 19 | 20 | 27 | 28 | 29 | ); 30 | }; 31 | 32 | export default Nav; 33 | -------------------------------------------------------------------------------- /components/search.js: -------------------------------------------------------------------------------- 1 | /**@jsxImportSource theme-ui*/ 2 | 3 | import { Container, Flex } from "theme-ui"; 4 | import { Search as Search_Icon } from "react-feather"; 5 | import { useRef } from "react"; 6 | 7 | const Search = ({ original_data, set_data, ...props }) => { 8 | const input_ref = useRef(); 9 | 10 | const on_change = () => { 11 | const search = input_ref.current.value; 12 | 13 | const new_data = original_data.filter(({ name }) => { 14 | const condition = name.toLowerCase().includes(search.toLowerCase()); 15 | 16 | return condition; 17 | }); 18 | set_data(new_data); 19 | }; 20 | 21 | return ( 22 | 23 | 41 | 42 | 56 | 57 | 58 | ); 59 | }; 60 | 61 | export default Search; 62 | -------------------------------------------------------------------------------- /lib/css/tippy.css: -------------------------------------------------------------------------------- 1 | .tippy-box[data-animation='fade'][data-state='hidden'] { 2 | opacity: 0; 3 | } 4 | [data-tippy-root] { 5 | max-width: calc(100vw - 10px); 6 | } 7 | .tippy-box { 8 | position: relative; 9 | background-color: #ec3750; 10 | color: #fff; 11 | border-radius: 4px; 12 | font-size: 14px; 13 | line-height: 1.4; 14 | outline: 0; 15 | transition-property: transform, visibility, opacity; 16 | } 17 | .tippy-box[data-placement^='top'] > .tippy-arrow { 18 | bottom: 0; 19 | } 20 | .tippy-box[data-placement^='top'] > .tippy-arrow:before { 21 | bottom: -7px; 22 | left: 0; 23 | border-width: 8px 8px 0; 24 | border-top-color: initial; 25 | transform-origin: center top; 26 | } 27 | .tippy-box[data-placement^='bottom'] > .tippy-arrow { 28 | top: 0; 29 | } 30 | .tippy-box[data-placement^='bottom'] > .tippy-arrow:before { 31 | top: -7px; 32 | left: 0; 33 | border-width: 0 8px 8px; 34 | border-bottom-color: initial; 35 | transform-origin: center bottom; 36 | } 37 | .tippy-box[data-placement^='left'] > .tippy-arrow { 38 | right: 0; 39 | } 40 | .tippy-box[data-placement^='left'] > .tippy-arrow:before { 41 | border-width: 8px 0 8px 8px; 42 | border-left-color: initial; 43 | right: -7px; 44 | transform-origin: center left; 45 | } 46 | .tippy-box[data-placement^='right'] > .tippy-arrow { 47 | left: 0; 48 | } 49 | .tippy-box[data-placement^='right'] > .tippy-arrow:before { 50 | left: -7px; 51 | border-width: 8px 8px 8px 0; 52 | border-right-color: initial; 53 | transform-origin: center right; 54 | } 55 | .tippy-box[data-inertia][data-state='visible'] { 56 | transition-timing-function: cubic-bezier(0.54, 1.5, 0.38, 1.11); 57 | } 58 | .tippy-arrow { 59 | width: 16px; 60 | height: 16px; 61 | color: #ec3750; 62 | } 63 | .tippy-arrow:before { 64 | content: ''; 65 | position: absolute; 66 | border-color: transparent; 67 | border-style: solid; 68 | } 69 | .tippy-content { 70 | position: relative; 71 | padding: 5px 9px; 72 | z-index: 1; 73 | } 74 | -------------------------------------------------------------------------------- /lib/data.js: -------------------------------------------------------------------------------- 1 | const data = [ 2 | { 3 | text: `Zephyr train is here 🚝`, 4 | img_url: `https://cloud-nc09p1kqr-hack-club-bot.vercel.app/0ezgif.com-gif-maker.gif`, 5 | }, 6 | { 7 | text: `We are here :), this is the best trip that a teenager can have.`, 8 | img_url: `https://cloud-anw1okjxh-hack-club-bot.vercel.app/0img_5771.jpg`, 9 | }, 10 | { 11 | text: `We are unstoppable`, 12 | img_url: `https://cloud-nc09p1kqr-hack-club-bot.vercel.app/0ezgif.com-gif-maker.gif`, 13 | }, 14 | { 15 | text: `This is cool 👀`, 16 | img_url: `https://cloud-anw1okjxh-hack-club-bot.vercel.app/1img_20210718_163014514.jpg`, 17 | }, 18 | { 19 | text: `Here we gooooooooo!`, 20 | img_url: `https://cloud-anw1okjxh-hack-club-bot.vercel.app/2img_20210718_163021214.jpg`, 21 | }, 22 | { 23 | text: `Poggerssssss`, 24 | img_url: `https://cloud-anw1okjxh-hack-club-bot.vercel.app/3pxl_20210719_062948946.jpg`, 25 | }, 26 | { 27 | text: `Hack Club is cool`, 28 | img_url: `https://cloud-anw1okjxh-hack-club-bot.vercel.app/4img_5653.jpg`, 29 | }, 30 | ]; 31 | 32 | export default data; 33 | -------------------------------------------------------------------------------- /lib/firebase/add.js: -------------------------------------------------------------------------------- 1 | const db = require("./firebase"); 2 | const _ = require("ramda"); 3 | 4 | const fb_add = async (collection_id, doc_id, obj) => 5 | await db 6 | .collection(collection_id) 7 | .doc(doc_id) 8 | .set(obj, { merge: true }) 9 | .then(() => { 10 | return true; 11 | }) 12 | .catch((error) => { 13 | return false; 14 | }); 15 | 16 | const add = _.curry(fb_add); 17 | 18 | module.exports = add; 19 | -------------------------------------------------------------------------------- /lib/firebase/add_club.js: -------------------------------------------------------------------------------- 1 | const add = require("./add"); 2 | 3 | const data = { 4 | path: "", 5 | name: "Hack Club COET", 6 | desc: "hack club cgc was founded in 2019 with a dream of making a cool tech community in cgc! we are now a happy team of 13 members.", 7 | auth_group: ["U01TM2KUPCH"], 8 | members: ["U01TM2KUPCH"], 9 | cover: 10 | "https://cloud-lzk8azrls-hack-club-bot.vercel.app/0screen_shot_2021-08-05_at_10.58.22.png", 11 | logo: "https://cloud-4nvqu7g0r-hack-club-bot.vercel.app/0cgchack.png", 12 | ships: 0, 13 | meetings: 0, 14 | events: 0, 15 | hackathons: 0, 16 | points: 0, 17 | t_points: 0, 18 | }; 19 | 20 | const add_club = (obj) => { 21 | add("clubs", obj.name, obj); 22 | }; 23 | 24 | add_club(data); 25 | 26 | module.exports = add_club; 27 | -------------------------------------------------------------------------------- /lib/firebase/add_team.js: -------------------------------------------------------------------------------- 1 | const db = require("./firebase"); 2 | const _ = require("ramda"); 3 | 4 | const person = [ 5 | { 6 | name: "Shubham Gupta", 7 | role: "lead/member", 8 | img_url: 9 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/Shubham.JPG", 10 | is_lead: true, 11 | slack_id: "U01F9A5R0R1", 12 | }, 13 | { 14 | name: "Keshav Kumar Rohila", 15 | role: "co-lead/member", 16 | is_lead: true, 17 | img_url: 18 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/keshav.png", 19 | slack_id: "U028APVDDQX", 20 | }, 21 | { 22 | name: "Vinay Sharma", 23 | role: "Secretory/member", 24 | is_lead: false, 25 | img_url: 26 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/vinay.jpg", 27 | slack_id: "U028WFDPML4", 28 | }, 29 | { 30 | name: "Shristi Agarwal", 31 | role: "Jr. Secretory/member", 32 | is_lead: false, 33 | img_url: 34 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/Shristi.jpg", 35 | slack_id: "U0293069FBK", 36 | }, 37 | { 38 | name: "Manash Khetan", 39 | role: "Technical head/member", 40 | is_lead: false, 41 | img_url: 42 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/manash.jpg", 43 | slack_id: "U028RSQ2U5R", 44 | }, 45 | { 46 | name: "Shruti Agarwal", 47 | role: "Web Developer/member", 48 | is_lead: false, 49 | img_url: 50 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/shruti.jpg", 51 | slack_id: "U029E17C89W", 52 | }, 53 | { 54 | name: "Ritika Kumawat", 55 | role: "App Developer/member", 56 | is_lead: false, 57 | img_url: 58 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/ritika.jpg", 59 | slack_id: "U028RCQ7S2W", 60 | }, 61 | { 62 | name: "Deepak Verma", 63 | role: "Management Team/member", 64 | is_lead: false, 65 | img_url: 66 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/Deepak.jpg", 67 | slack_id: "U02B6S2263G", 68 | }, 69 | { 70 | name: "Pooja Verma", 71 | role: "Management Team/member", 72 | is_lead: false, 73 | img_url: 74 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/pooja.jpg", 75 | slack_id: "U029F3TFX8Q", 76 | }, 77 | { 78 | name: "Vikram Kumar", 79 | role: "Editorial/member", 80 | is_lead: false, 81 | img_url: 82 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/vikram.jpg", 83 | slack_id: "U029DV9LQRW", 84 | }, 85 | { 86 | name: "Ira Goyal", 87 | role: "Editorial/member", 88 | is_lead: false, 89 | img_url: 90 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/791c28e836cf5ff73626e30139df4cdba450d89e/Hack%20Club%20BKBIET/ira%20Goyal.jpg", 91 | slack_id: "U02BDJYUBM0", 92 | }, 93 | { 94 | name: "Ishan Agarwal", 95 | role: "Designer/member", 96 | is_lead: false, 97 | img_url: 98 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/791c28e836cf5ff73626e30139df4cdba450d89e/Hack%20Club%20BKBIET/Ishan.jpg", 99 | slack_id: "slack_id", 100 | }, 101 | { 102 | name: "Dheeraj Sharma", 103 | role: "Designer/member", 104 | is_lead: false, 105 | img_url: 106 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/dheeraj.jpg", 107 | slack_id: "U028Q9195B4", 108 | }, 109 | { 110 | name: "Arjun Sharma", 111 | role: "Public Relations/member", 112 | is_lead: false, 113 | img_url: 114 | "https://github.com/HackClub-BKBIET/Members-Photos/blob/main/Hack%20Club%20BKBIET/arjun.jpg", 115 | slack_id: "U029DM7S6GG", 116 | }, 117 | ]; 118 | 119 | const person_2 = [ 120 | { 121 | name: "Fadhil Abdulla", 122 | role: "lead", 123 | img_url: "https://cloud-rab0ysldi-hack-club-bot.vercel.app/1image.png", 124 | slack_id: "U01TM2KUPCH", 125 | is_lead: yes, 126 | }, 127 | { 128 | name: "Aditya Praveen", 129 | role: "member", 130 | img_url: "https://cloud-rab0ysldi-hack-club-bot.vercel.app/3image.png", 131 | slack_id: "U021TQP729K", 132 | is_lead: no, 133 | }, 134 | 135 | { 136 | name: " Amarjith Ajayababu T K", 137 | role: "member", 138 | img_url: "https://cloud-rab0ysldi-hack-club-bot.vercel.app/1image.png", 139 | slack_id: "U025YGHNV6V", 140 | is_lead: no, 141 | }, 142 | 143 | { 144 | name: "Basith", 145 | role: "member", 146 | img_url: "https://cloud-rab0ysldi-hack-club-bot.vercel.app/3image.png", 147 | slack_id: "U021WSW90M8", 148 | is_lead: no, 149 | }, 150 | ]; 151 | 152 | const add_team = async (club_name, person) => 153 | await db 154 | .collection("clubs") 155 | .doc(club_name) 156 | .collection("team") 157 | .add(person, { merge: true }) 158 | .then(() => { 159 | return true; 160 | }) 161 | .catch((error) => { 162 | return false; 163 | }); 164 | 165 | person.forEach(async (obj) => { 166 | await add_team("Hack Club BKBIET", obj); 167 | }); 168 | 169 | module.exports = add_team; 170 | -------------------------------------------------------------------------------- /lib/firebase/data.js: -------------------------------------------------------------------------------- 1 | const person_fact = (name, role, img_url) => ({ 2 | name, 3 | role, 4 | img_url, 5 | }); 6 | 7 | const data_fact = { 8 | logo: "", 9 | name: "", 10 | desc: "", 11 | t_points: 0, 12 | stats: { 13 | ships: 0, 14 | hackathons: 0, 15 | meetings: 0, 16 | events: 0, 17 | points: 0, 18 | }, 19 | }; 20 | 21 | //ship: 30 22 | // hackathons: 500 23 | // meetings: 50 24 | // events: 200 25 | 26 | const team = [ 27 | { 28 | img_url: "https://cloud-rab0ysldi-hack-club-bot.vercel.app/0image.png", 29 | name: "Priya Gupta", 30 | role: "lead", 31 | }, 32 | { 33 | img_url: "https://cloud-rab0ysldi-hack-club-bot.vercel.app/1image.png", 34 | name: "Aryan Joshi", 35 | role: "lead", 36 | }, 37 | { 38 | img_url: "https://cloud-rab0ysldi-hack-club-bot.vercel.app/2image.png", 39 | name: "Riya Aggarwal", 40 | role: "member", 41 | }, 42 | { 43 | img_url: "https://cloud-rab0ysldi-hack-club-bot.vercel.app/3image.png", 44 | name: "Rohtansh Sehgal", 45 | role: "member", 46 | }, 47 | { 48 | img_url: "https://cloud-52f856xi2-hack-club-bot.vercel.app/0image.png", 49 | name: "Rajeev Dogra", 50 | role: "lead", 51 | }, 52 | ]; 53 | 54 | const clubs = [ 55 | { 56 | logo: "https://cloud-4nvqu7g0r-hack-club-bot.vercel.app/0cgchack.png", 57 | name: "Hack Club CGC", 58 | desc: "hack club cgc was founded in 2019 with a dream of making a cool tech community in cgc! we are now a happy team of 13 members.", 59 | ships: 1, 60 | hackathons: 0, 61 | meetings: 1, 62 | events: 0, 63 | points: 80, 64 | t_points: 80, 65 | team, 66 | }, 67 | { 68 | logo: "https://cloud-r0dw7pkp2-hack-club-bot.vercel.app/0logo__recovered_.png", 69 | name: "Hack Club SIAS", 70 | desc: "hack club sias was founded in 2019 with a dream of making a cool tech community in cgc! we are now a happy team of 13 members.", 71 | ships: 0, 72 | hackathons: 0, 73 | meetings: 1, 74 | events: 0, 75 | points: 50, 76 | t_points: 50, 77 | team, 78 | }, 79 | { 80 | logo: "https://cloud-53n96fj1j-hack-club-bot.vercel.app/0igdp.jpeg", 81 | name: "Hack Club COET", 82 | desc: "hack club coet was founded in 2019 with a dream of making a cool tech community in cgc! we are now a happy team of 13 members.", 83 | ships: 1, 84 | hackathons: 0, 85 | meetings: 2, 86 | events: 0, 87 | points: 130, 88 | t_points: 130, 89 | team, 90 | }, 91 | { 92 | logo: "https://cloud-btfq9z0jg-hack-club-bot.vercel.app/0hackclub_bkbiet.png", 93 | name: "Hack Club BKBIET", 94 | desc: "hack club bkbiet was founded in 2019 with a dream of making a cool tech community in cgc! we are now a happy team of 13 members.", 95 | ships: 2, 96 | hackathons: 0, 97 | meetings: 0, 98 | events: 0, 99 | points: 60, 100 | t_points: 60, 101 | team, 102 | }, 103 | { 104 | logo: "https://cloud-r89ihrmd4-hack-club-bot.vercel.app/0image.png", 105 | name: "Hack Club NUV", 106 | desc: "hack club nuv was founded in 2019 with a dream of making a cool tech community in cgc! we are now a happy team of 13 members.", 107 | ships: 1, 108 | hackathons: 0, 109 | meetings: 3, 110 | events: 0, 111 | points: 180, 112 | t_points: 180, 113 | team, 114 | }, 115 | { 116 | logo: "https://cloud-ie0qixa93-hack-club-bot.vercel.app/0image.png", 117 | name: "Hack Club DPS", 118 | desc: "hack club dps was founded in 2019 with a dream of making a cool tech community in cgc! we are now a happy team of 13 members.", 119 | ships: 3, 120 | hackathons: 0, 121 | meetings: 0, 122 | events: 0, 123 | points: 90, 124 | t_points: 90, 125 | team, 126 | }, 127 | ]; 128 | 129 | module.exports.clubs = clubs; 130 | 131 | // team should be another sub_collection 132 | -------------------------------------------------------------------------------- /lib/firebase/firebase.js: -------------------------------------------------------------------------------- 1 | const firebase = require("firebase"); 2 | require("dotenv").config(); 3 | 4 | if (firebase.apps.length === 0) { 5 | const firebaseApp = firebase.initializeApp({ 6 | apiKey: process.env.apiKey, 7 | authDomain: process.env.authDomain, 8 | projectId: process.env.projectId, 9 | storageBucket: process.env.storageBucket, 10 | messagingSenderId: process.env.messagingSenderId, 11 | appId: process.env.appId, 12 | measurementId: process.env.measurementId, 13 | }); 14 | } 15 | 16 | module.exports = firebase.apps[0].firestore(); 17 | -------------------------------------------------------------------------------- /lib/firebase/get_all_clubs.js: -------------------------------------------------------------------------------- 1 | const db = require("./firebase"); 2 | 3 | const get_all_clubs = async () => { 4 | const data = []; 5 | 6 | await db 7 | .collection("clubs") 8 | .orderBy("points", "desc") 9 | .get() 10 | .then((qs) => { 11 | qs.forEach(async (doc) => { 12 | data.push(await doc.data()); 13 | }); 14 | }); 15 | return data; 16 | }; 17 | 18 | module.exports = get_all_clubs; 19 | -------------------------------------------------------------------------------- /lib/firebase/get_all_paths.js: -------------------------------------------------------------------------------- 1 | const db = require("./firebase"); 2 | 3 | const get_all_paths = async () => { 4 | const paths = []; 5 | 6 | await db 7 | .collection("clubs") 8 | .orderBy("points", "desc") 9 | .get() 10 | .then((qs) => { 11 | qs.forEach(async (doc) => { 12 | const { path } = await doc.data(); 13 | paths.push(path); 14 | }); 15 | }); 16 | return paths; 17 | }; 18 | 19 | module.exports = get_all_paths; 20 | -------------------------------------------------------------------------------- /lib/firebase/get_club_data.js: -------------------------------------------------------------------------------- 1 | const { clubs } = require("./data"); 2 | const db = require("./firebase"); 3 | 4 | const get_club_data = async (path) => { 5 | const data = []; 6 | 7 | await db 8 | .collection("clubs") 9 | .where("path", "==", path) 10 | .get() 11 | .then((qs) => { 12 | qs.forEach(async (doc) => { 13 | const doc_data = await doc.data(); 14 | data.push(doc_data); 15 | }); 16 | }); 17 | return data[0]; 18 | }; 19 | 20 | module.exports = get_club_data; 21 | -------------------------------------------------------------------------------- /lib/firebase/get_posts_data.js: -------------------------------------------------------------------------------- 1 | const db = require("./firebase"); 2 | const get_club_data = require("./get_club_data"); 3 | 4 | const { pick, keys, filter } = require("ramda"); 5 | 6 | const get_posts_data = async (slug) => { 7 | const data = []; 8 | const { name } = await get_club_data(slug); 9 | 10 | await db 11 | .collection("clubs") 12 | .doc(name) 13 | .collection("posts") 14 | .orderBy("created", "desc") 15 | .limit(25) 16 | .get() 17 | .then((qs) => { 18 | qs.forEach(async (doc) => { 19 | const doc_data = await doc.data(); 20 | 21 | const props = filter((key) => key != "created", keys(doc_data)); 22 | 23 | data.push(pick(props, doc_data)); 24 | }); 25 | }); 26 | 27 | return data; 28 | }; 29 | 30 | module.exports = get_posts_data; 31 | -------------------------------------------------------------------------------- /lib/firebase/get_team_data.js: -------------------------------------------------------------------------------- 1 | const db = require("./firebase"); 2 | const get_club_data = require("./get_club_data"); 3 | 4 | const get_team_data = async (slug) => { 5 | const data = []; 6 | const { name } = await get_club_data(slug); 7 | 8 | await db 9 | .collection("clubs") 10 | .doc(name) 11 | .collection("team") 12 | .get() 13 | .then((qs) => { 14 | qs.forEach(async (doc) => { 15 | data.push(await doc.data()); 16 | }); 17 | }); 18 | 19 | return data; 20 | }; 21 | 22 | module.exports = get_team_data; 23 | -------------------------------------------------------------------------------- /lib/firebase/index.js: -------------------------------------------------------------------------------- 1 | module.exports.get_all_clubs = require("./get_all_clubs"); 2 | module.exports.get_all_paths = require("./get_all_paths"); 3 | module.exports.get_club_data = require("./get_club_data"); 4 | module.exports.get_team_data = require("./get_team_data"); 5 | module.exports.get_posts_data = require("./get_posts_data"); 6 | -------------------------------------------------------------------------------- /lib/firebase/script.js: -------------------------------------------------------------------------------- 1 | const add_club = require("./add_club"); 2 | const add_team = require("./add_team"); 3 | const { clubs } = require("./data"); 4 | 5 | clubs.forEach(({ name, team }) => { 6 | team.forEach((person) => { 7 | add_team(name, person); 8 | }); 9 | }); 10 | 11 | //clubs.forEach((obj) => { 12 | //const temp_obj = new Object(obj); 13 | //delete temp_obj["team"]; 14 | //add_club(temp_obj); 15 | //}); 16 | -------------------------------------------------------------------------------- /lib/theme/index.js: -------------------------------------------------------------------------------- 1 | import base_theme from "@hackclub/theme"; 2 | import { darken } from "@theme-ui/color"; 3 | 4 | const custom_theme = { 5 | ...base_theme, 6 | 7 | subt: { 8 | color: "muted", 9 | my: [0], 10 | }, 11 | 12 | heading: { 13 | ...base_theme?.heading, 14 | fontSize: [4, 5], 15 | my: [0], 16 | }, 17 | 18 | para: { 19 | ...base_theme?.para, 20 | fontSize: [1, 2], 21 | //color: "sheet", 22 | }, 23 | 24 | wavy: { 25 | ...base_theme?.wavy, 26 | textDecorationLine: "underline", 27 | textDecorationStyle: "wavy", 28 | }, 29 | 30 | cont: { 31 | ...base_theme?.cont, 32 | mt: [4, 5], 33 | }, 34 | }; 35 | 36 | /**Disable dark mode */ 37 | //custom_theme.useColorSchemeMediaQuery = false; 38 | 39 | // making colors of light theme and dark theme the same 40 | custom_theme.colors = { 41 | ...custom_theme.colors, 42 | ...custom_theme.colors.modes.dark, 43 | }; 44 | 45 | custom_theme.styles.root = { 46 | ...custom_theme.styles.root, 47 | //bg: darken("white", 0.03), 48 | //bg: "dark", 49 | }; 50 | 51 | export default custom_theme; 52 | -------------------------------------------------------------------------------- /lib/utils/get_slack_username.js: -------------------------------------------------------------------------------- 1 | const { WebClient, LogLevel } = require("@slack/web-api"); 2 | require('dotenv').config() 3 | 4 | 5 | const get_slack_username = async (slack_id) => { 6 | const oauth_token = process.env.OAUTH_TOKEN; 7 | 8 | const client = new WebClient(oauth_token, { 9 | logLevel: LogLevel.DEBUG, 10 | }); 11 | 12 | return (await client.users.info({user:slack_id})).user.name 13 | } 14 | 15 | module.exports = get_slack_username -------------------------------------------------------------------------------- /lib/utils/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get_slack_username: require('./get_slack_username'), 3 | scrapbook_exists: require('./scrapbook_exists') 4 | } -------------------------------------------------------------------------------- /lib/utils/scrapbook_exists.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios') 2 | const {parse} = require('node-html-parser') 3 | 4 | const scrapbook_exists = async (username) => { 5 | 6 | 7 | const res = await axios.get(`https://scrapbook.hackclub.com/${username}`) 8 | const htmlDoc= parse(res.data, 'text/html') 9 | try{ 10 | const titleValue = htmlDoc.getElementsByTagName('title')[0].innerText 11 | 12 | return !titleValue.includes('404')} 13 | catch(err){ 14 | console.log('error happened for'); 15 | console.log('username =>',username); 16 | console.log('res',htmlDoc); 17 | } 18 | } 19 | 20 | module.exports = scrapbook_exists; -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | images: { 3 | domains: ["hackclub.com", "vercel.app"], 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leaderboard", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "@hackclub/meta": "^1.1.32", 12 | "@hackclub/theme": "^0.3.3", 13 | "@slack/bolt": "^3.11.0", 14 | "@slack/web-api": "^6.7.1", 15 | "@theme-ui/color": "^0.10.0", 16 | "@tippyjs/react": "^4.2.5", 17 | "axios": "^0.26.1", 18 | "dotenv": "^10.0.0", 19 | "firebase": "^8.9.0", 20 | "lodash": "^4.17.21", 21 | "next": "11.0.1", 22 | "node-html-parser": "^5.3.3", 23 | "ramda": "^0.27.1", 24 | "react": "17.0.2", 25 | "react-dom": "17.0.2", 26 | "react-feather": "^2.0.9", 27 | "react-masonry-css": "^1.0.16", 28 | "react-player": "^2.9.0", 29 | "theme-ui": "^0.10.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import { ThemeProvider } from "theme-ui"; 2 | import "../lib/css/tippy.css"; 3 | 4 | import { Github } from "../components/index"; 5 | import theme from "../lib/theme/index"; 6 | 7 | const Custom_App = ({ Component, pageProps }) => { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | }; 15 | 16 | export default Custom_App; 17 | -------------------------------------------------------------------------------- /pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.status(200).json({ name: 'John Doe' }) 5 | } 6 | -------------------------------------------------------------------------------- /pages/club/[slug].js: -------------------------------------------------------------------------------- 1 | import { ascend, difference, prop, sort } from "ramda"; 2 | import { Nav, Meta } from "../../components"; 3 | import { 4 | Gallery, 5 | Hero, 6 | Socials, 7 | Stats, 8 | Team, 9 | } from "../../components/club/index"; 10 | 11 | const Club_Page = ({ club_data, team_data, posts_data }) => { 12 | return ( 13 | <> 14 | 20 | 21 |