Compare commits

..
14 Commits
Author SHA1 Message Date
euxzy 3e232dcdc2 feat(dimentorin): slicing landing page menu mentoring 2025-07-10 08:01:11 +07:00
Muhamad Rijal ec13f2c693 feat(dimentorin): slicing landing page (#46)
* feat(landing): slicing navigation bar

* feat(landing): slicing hero section

* feat(landing): slicing what we offer section

* feat(landing): add animation on hero and what we offer section

* feat(landing): slicing testimonial section

* feat(landing): change the animation for what we offer section

* feat: add utility for readable looping and conditional rendering of components

* feat(landing): slicing faq section

* feat(landing): change border radius of card on `what we offer` and `testimonial` section

* feat(landing): slicing cta section

* feat: modify accordion component

* feat(landing): add shape background at faq section

* feat(landing): slicing footer

* feat: toggle header visibility on scroll
2025-06-30 09:24:37 +07:00
I Made Ocy Darma Putra 302ee37ca1 feat(docker): all projects (#36)
* fix: docker

* fix landing

* chore(landing): add outputFileTracingRoot to next config

* ci: add github workflow for landing deployment via ssh and docker compose

* chore: add docker-compose file for landing app build and run

* feat docker
2025-06-19 11:17:21 +07:00
Naufal Azmi b7282f9c99 Resend OTP (#34)
* feat: responsive

* fix: success register

* feat: auth login responsive && auth login implementation

* fix: login page button disabled & register page

* fix: conflict

* fix: button disabled when loading

* feat: register and otp integration

* Update middleware.ts

* feat: OTP Resend
2025-06-18 18:50:06 +07:00
Rasyid 2c347d1cc5 feat: add ui for roadmap ui (#35)
* fix: correct link for Roadmap navigation item

* feat: add feature request and projects voting components

* fix: correct spelling of 'Certificate' in ProjectsVote component

* feat: add Request Feature popup with responsive dialog and drawer components

* feat: enhance Header component with mobile menu animations and improved navigation styling

* refactor: simplify Header component by removing unused scroll handling and improving mobile menu structure

* fix: replace motion span with static span for header underline

* fix: update FeatureRequestCTA text for clarity and adjust page layout margins

* fix: remove DialogDescription from RequestFeaturePopup and update textarea placeholder for clarity

* fix: remove DrawerDescription from RequestFeaturePopup for cleaner UI

* fix: remove unused icon exports from icons

* fix: replace XIcon with LuX in DialogClose for consistency

* fix: remove unused icon export from index for cleaner module structure
2025-06-18 18:40:19 +07:00
Rasyid 791f43986d feat: landing auth integration & landing ui improvements (#33)
* feat: setup openapi libs for landing

* feat: seperate landing layouts

* feat: movee landing providers

* feat: add auth layout

* feat: implement cookie management for access and refresh tokens

* feat: replace Inter font with Bai Jamjuree in layout and add font utility

* feat: add signin

* feat: add Poppins font to the font utility

* feat: expand theme colors in index.css for improved styling options

* feat: update dependencies and enhance button and form components with new variants and context

* feat: move old components to __old__ dir

* feat: add react query support

* feat: hide the footer

* fix: header style

* feat: replace Image component with LogoSimple in Header and update Logo component to accept props

* fix: update label for tutorial stat in hero-stats.json

* feat: implement EventsPage component with event listing and details

* feat: add signup button and page

* feat: add HERO_CONTENT data and integrate into Hero component

* fix: update navigations import to uppercase and add missing Testimoni entry

* feat: implement testimonials display and add submission page

* fix: correct link path for testimonial submission

* feat: add communites component and integrate social links from JSON data

* fix: adjust grid gap in Communities component for better layout

* fix: update font imports in layout components for consistency

* fix: replace text logo with LogoSimple component in Footer and restore Footer in Layout

* feat: add TestimonialSection component and update testimonials data

* fix: update section ID from 'komunitas' to 'community' for consistency

* feat: add CTASection component with interactive elements and background pattern

* fix: update join URL in hero content for consistency

* fix: update text in CTASection for improved emphasis and consistency

* feat: add CommunitySection component and integrate it into the main page

* feat: update Footer component to use dynamic navigation and social links

* feat: implement HeroSection component with dynamic content and animations

* refactor: replace hardcoded testimonials with dynamic data from JSON

* feat: add signup page

* feat: integrate Turnstile captcha verification in signup process

* feat: implement verification page

* feat: add signin link to the signup page

* feat: add "Forgot Password?" link to the signin form

* refactor: clean up unused ThemeProvider code and CSS variables

* feat: add base styles for borders and background to improve UI consistency

* feat: implement forgot password functionality with validation and UI components

* fix: update password validation rules for clarity and consistency

* feat: enable rich colors for Toaster component in layout

* feat: implement reset password functionality with validation and UI components

* feat: implement Turnstile captcha verification for forgot password and signup actions

* refactor: remove console log and enhance error handling in signin and resend OTP actions

* feat: add navigation entries for Roadmap and Artikel sections

* feat: create initial Page component for articles section

* feat: update footer component with additional social media links and icons

* feat: remove all unused components in landing

* chore: add @radix-ui/react-label deps

* feat: wrap VerificationTabs in Suspense

* feat: update .env.example to include TURNSTILE_SECRET_KEY and correct NEXT_PUBLIC_TURNSTILE_SITEKEY
2025-05-30 11:57:17 +07:00
Hafid Nur 9f25941a4a feat: gacha auth integration (#32)
* feat(gacha): register and login integration

* fix: navbar and gacha landing page

- display fullname when user authenticated
- fix styling and responsive

* fix: minor fix UI
2025-05-27 01:41:13 +07:00
Naufal Azmi aaf5b4262d Register and OTP (#31)
* feat: responsive

* fix: success register

* feat: auth login responsive && auth login implementation

* fix: login page button disabled & register page

* fix: conflict

* fix: button disabled when loading

* feat: register and otp integration

* Update middleware.ts
2025-05-26 20:49:57 +07:00
Naufal Azmi 0f46244d2b Fix conflict and add disabled button when invalid input (#30)
* feat: responsive

* fix: success register

* feat: auth login responsive && auth login implementation

* fix: login page button disabled & register page

* fix: conflict

* fix: button disabled when loading
2025-05-26 17:07:51 +07:00
Rasyid dd03b3da85 chore: remove cms and fix some styles (#29)
* chore: remove all references to PayloadCMS

* fix: nextjs landing utils

* feat: refactor community, features, hero, learning resources, and testimonials components to use external JSON data

* fix:remove hero logo box

* fix: remove unused image in public

* fix: change logo.png to logo.webp

* fix: update button styles for improved visibility

* chore: restructure component organization

* fix: update import path for global styles in layout component

* fix: adjust alignment of hero stats section for better layout

* fix: update testimonials placeholder sample data

* fix: update header component to use router for navigation and add signin page
2025-05-25 15:13:44 +07:00
Maulana Sodiqin 9a0fee65a5 fixing so much trouble 2025-05-23 00:28:29 +07:00
Maulana Sodiqin 376e646c10 feat: add vercel json 2025-05-22 22:31:04 +07:00
Maulana Sodiqin f8cd57a1cf chore: update readme and env example 2025-05-20 11:09:14 +07:00
Rasyid 5618a8e99b fix: hero section responsiveness (#28)
* fix: hero section responsiveness

* fix: adjust max-width for hero section on smaller screens

* fix: increase title font size in hero section
2025-05-17 00:58:23 +07:00
261 changed files with 10444 additions and 9129 deletions
-14
View File
@@ -1,14 +0,0 @@
# API Endpoint
VITE_API_URL=
# Payload CMS Secret Key (minimum 32 characters)
CMS_SECRET=your-very-long-secret-key
# PostgreSQL Connection String
CMS_POSTGRES_URL=postgres://user:password@host:port/database
# S3 Storage Configuration
CMS_STORAGE_ENDPOINT=https://your-s3-endpoint.com
CMS_STORAGE_ACCESS_KEY_ID=your-access-key-id
CMS_STORAGE_SECRET_ACCESS_KEY=your-secret-access-key
CMS_STORAGE_REGION=ap-southeast-1
+33
View File
@@ -0,0 +1,33 @@
name: Deploy Landing
on:
push:
paths:
- 'apps/landing/**' # INI BASED ON PATH CHANGES JADI NTAR KALAU ADA PUSH DIISNI OTOMATIS DEPLOY
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
set -e
if [ ! -d ~/imphnen-frontend-service ]; then
git clone https://github.com/IMPHNEN/imphnen-frontend-service.git ~/imphnen-frontend-service
else
cd ~/imphnen-frontend-service && git pull
fi
echo "NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL }}" > ~/imphnen-frontend-service/apps/landing/.env
docker compose -f ~/imphnen-frontend-service/docker-compose-landing.yml down || true
docker compose -f ~/imphnen-frontend-service/docker-compose-landing.yml build
docker compose -f ~/imphnen-frontend-service/docker-compose-landing.yml up -d
docker image prune -af
+25 -4
View File
@@ -6,9 +6,10 @@
This repository is a **monorepo** for all frontend services of IMPHNEN. The monorepo includes three main applications: This repository is a **monorepo** for all frontend services of IMPHNEN. The monorepo includes three main applications:
1. **Gacha** - Application for <a href="https://gacha.imphnen.dev/" target="_blank">gacha website</a>. 1. **Gacha** - Application for <a href="https://gacha.imphnen.dev/" target="_blank">Gacha Website</a>.
2. **Backoffice** - Application for internal management. 2. **Backoffice** - Application for <a href="https://gacha.imphnen.dev/" target="_blank">Internal Management Website</a>.
3. **Dimentorin** - Application for mentoring services. 3. **Dimentorin** - Application for <a href="https://dimentorin.imphnen.dev/" target="_blank">Mentoring Service</a>.
4. **Landing Page** - Application for <a href="https://imphnen.dev/" target="_blank">Landing Page</a>.
## How to install ## How to install
@@ -24,6 +25,15 @@ This repository is a **monorepo** for all frontend services of IMPHNEN. The mono
## How to run ## How to run
### Setup Environment Variables
Before running the applications, you need to set up the environment variables. You can do this by copying the `.env.example` file to `.env` and modifying the values according to your needs.
```sh
cd apps/{appname}
cp .env.example .env
```
### Development ### Development
Use the following commands to run in development mode: Use the following commands to run in development mode:
@@ -40,6 +50,10 @@ Use the following commands to run in development mode:
```sh ```sh
npm run dimentorin:dev npm run dimentorin:dev
``` ```
- **Landing Page**:
```sh
npm run landing:dev
```
### Build ### Build
@@ -57,6 +71,10 @@ Use the following commands to build the applications:
```sh ```sh
npm run dimentorin:build npm run dimentorin:build
``` ```
- **Landing Page**:
```sh
npm run landing:build
```
### Production ### Production
@@ -74,6 +92,10 @@ Use the following commands to run the applications in production mode:
```sh ```sh
npm run dimentorin:prod npm run dimentorin:prod
``` ```
- **Landing Page**:
```sh
npm run landing:prod
```
### Storybook ### Storybook
@@ -87,7 +109,6 @@ This repository uses Storybook to develop, test, and document UI components in a
npm run ui:storybook npm run ui:storybook
``` ```
- **Run Unit Test** - **Run Unit Test**
This command runs unit tests for the UI components to ensure they function as expected. This command runs unit tests for the UI components to ensure they function as expected.
+1
View File
@@ -0,0 +1 @@
VITE_API_URL=
@@ -18,7 +18,7 @@ import {
RowSelectionState, RowSelectionState,
} from '@tanstack/react-table'; } from '@tanstack/react-table';
import ModalEditAccount from './_components/modal-edit-account'; import ModalEditAccount from './_components/modal-edit-account';
import { useQueryState } from '../../hook/use-query-state'; import { useQueryState } from '@imphnen-frontend-service/utils';
interface Account { interface Account {
id: number; id: number;
@@ -166,7 +166,7 @@ export const Components: FC = (): ReactElement => {
</Button> </Button>
{showFilter && ( {showFilter && (
<div className="absolute right-0 top-[calc(100%+12px)] z-10 shadow-lg"> <div className="absolute right-0 top-[calc(100%+12px)] z-10 shadow-lg">
<Filter onClose={() => setShowFilter(false)} /> <Filter onClose={() => setShowFilter(false)} options={[]} />
</div> </div>
)} )}
</div> </div>
@@ -10,7 +10,7 @@ import { FC, Fragment, ReactElement, useState } from 'react';
import ModalAddItem from './_components/modal-add-item'; import ModalAddItem from './_components/modal-add-item';
import ModalEditItem from './_components/modal-edit-item'; import ModalEditItem from './_components/modal-edit-item';
import ModalDeleteItem from './_components/modal-delete-item'; import ModalDeleteItem from './_components/modal-delete-item';
import { useQueryState } from '../../hook/use-query-state'; import { useQueryState } from '@imphnen-frontend-service/utils';
export const Components: FC = (): ReactElement => { export const Components: FC = (): ReactElement => {
const [showModalAddItem, setShowModalAddItem] = useState(false); const [showModalAddItem, setShowModalAddItem] = useState(false);
@@ -2,24 +2,19 @@ import { useForm } from 'react-hook-form';
import { import {
authLoginSchema, authLoginSchema,
TLoginRequest, TLoginRequest,
usePostLogin,
} from '@imphnen-frontend-service/service'; } from '@imphnen-frontend-service/service';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { toast } from 'sonner'; import { useSession } from '@imphnen-frontend-service/utils';
export const useLogin = () => { export const useLogin = () => {
const postLogin = usePostLogin();
const form = useForm<TLoginRequest>({ const form = useForm<TLoginRequest>({
resolver: zodResolver(authLoginSchema), resolver: zodResolver(authLoginSchema),
mode: 'all', mode: 'all',
}); });
const onSubmit = form.handleSubmit((data) => { const { signIn } = useSession();
postLogin.mutate(data, {
onSuccess: () => toast.success("Login sukses"), const onSubmit = form.handleSubmit((data) => signIn(data));
onError: (error) => toast.error(error.message),
});
});
return { return {
form, form,
@@ -32,7 +32,16 @@ export const Components: FC = (): ReactElement => {
size="lg" size="lg"
className="w-full" className="w-full"
/> />
<Button type="submit" size="md" className="w-full"> <Button
disabled={
form.formState.isSubmitting ||
form.formState.isValidating ||
!form.formState.isValid
}
type="submit"
size="md"
className="w-full"
>
Login Login
</Button> </Button>
</form> </form>
@@ -1,18 +0,0 @@
import { FC, ReactElement } from 'react';
import { Outlet } from 'react-router-dom';
import { BackofficeSidebar } from '@imphnen-frontend-service/ui/organisms';
export const AppLayout: FC = (): ReactElement => {
return (
<div className="bg-primary-50 min-h-screen flex justify-center">
<div className="bg-primary-50 min-h-screen w-full flex">
<BackofficeSidebar />
<div className="flex-1 overflow-auto lg:max-w-[1000px] 2xl:max-w-[1280px] mx-auto">
<Outlet />
</div>
</div>
</div>
);
};
export default AppLayout;
@@ -1,18 +0,0 @@
import { FC, ReactElement } from 'react';
import { Outlet } from 'react-router-dom';
import { BackofficeSidebar } from '@imphnen-frontend-service/ui/organisms';
export const AppLayout: FC = (): ReactElement => {
return (
<div className="bg-primary-50 min-h-screen flex justify-center">
<div className="bg-primary-50 min-h-screen w-full flex">
<BackofficeSidebar />
<div className="flex-1 overflow-auto lg:max-w-[1000px] 2xl:max-w-[1280px] mx-auto">
<Outlet />
</div>
</div>
</div>
);
};
export default AppLayout;
@@ -1,18 +0,0 @@
import { FC, ReactElement } from 'react';
import { Outlet } from 'react-router-dom';
import { BackofficeSidebar } from '@imphnen-frontend-service/ui/organisms';
export const AppLayout: FC = (): ReactElement => {
return (
<div className="bg-primary-50 min-h-screen flex justify-center">
<div className="bg-primary-50 min-h-screen w-full flex">
<BackofficeSidebar />
<div className="flex-1 overflow-auto lg:max-w-[1000px] 2xl:max-w-[1280px] mx-auto">
<Outlet />
</div>
</div>
</div>
);
};
export default AppLayout;
-18
View File
@@ -1,18 +0,0 @@
import { FC, ReactElement } from 'react';
import { Outlet } from 'react-router-dom';
import { BackofficeSidebar } from '@imphnen-frontend-service/ui/organisms';
export const AppLayout: FC = (): ReactElement => {
return (
<div className="bg-primary-50 min-h-screen flex justify-center">
<div className="bg-primary-50 min-h-screen w-full flex">
<BackofficeSidebar />
<div className="flex-1 overflow-auto lg:max-w-[1000px] 2xl:max-w-[1280px] mx-auto">
<Outlet />
</div>
</div>
</div>
);
};
export default AppLayout;
-18
View File
@@ -1,18 +0,0 @@
import { FC, ReactElement } from 'react';
import { Outlet } from 'react-router-dom';
import { BackofficeSidebar } from '@imphnen-frontend-service/ui/organisms';
export const AppLayout: FC = (): ReactElement => {
return (
<div className="bg-primary-50 min-h-screen flex justify-center">
<div className="bg-primary-50 min-h-screen w-full flex">
<BackofficeSidebar />
<div className="flex-1 overflow-auto lg:max-w-[1000px] 2xl:max-w-[1280px] mx-auto">
<Outlet />
</div>
</div>
</div>
);
};
export default AppLayout;
@@ -1,18 +0,0 @@
import { FC, ReactElement } from 'react';
import { Outlet } from 'react-router-dom';
import { BackofficeSidebar } from '@imphnen-frontend-service/ui/organisms';
export const AppLayout: FC = (): ReactElement => {
return (
<div className="bg-primary-50 min-h-screen flex justify-center">
<div className="bg-primary-50 min-h-screen w-full flex">
<BackofficeSidebar />
<div className="flex-1 overflow-auto lg:max-w-[1000px] 2xl:max-w-[1280px] mx-auto">
<Outlet />
</div>
</div>
</div>
);
};
export default AppLayout;
+100 -3
View File
@@ -1,11 +1,108 @@
import { LoaderFunctionArgs } from 'react-router-dom'; import {
PERMISSIONS,
SessionToken,
SessionUser,
} from '@imphnen-frontend-service/utils';
import { LoaderFunctionArgs, redirect } from 'react-router';
const mappingPublicRoutes = [
'/auth/login',
'/auth/forgot',
'/auth/new-password',
];
const mappingRoutePermissions = [
{
path: '/dashboard',
permissions: [],
},
{
path: '/users',
permissions: [PERMISSIONS.USERS.READ_LIST],
},
{
path: '/users/create',
permissions: [PERMISSIONS.USERS.CREATE],
},
{
path: '/users/update',
permissions: [PERMISSIONS.USERS.UPDATE],
},
{
path: '/users/detail',
permissions: [PERMISSIONS.USERS.READ_DETAIL],
},
{
path: '/roles',
permissions: [PERMISSIONS.ROLES.READ_LIST],
},
{
path: '/roles/create',
permissions: [PERMISSIONS.ROLES.CREATE],
},
{
path: '/roles/update',
permissions: [PERMISSIONS.ROLES.UPDATE],
},
{
path: '/roles/detail',
permissions: [PERMISSIONS.ROLES.READ_DETAIL],
},
{
path: '/permissions',
permissions: [PERMISSIONS.PERMISSIONS.READ_LIST],
},
{
path: '/permissions/create',
permissions: [PERMISSIONS.PERMISSIONS.CREATE],
},
{
path: '/permissions/update',
permissions: [PERMISSIONS.PERMISSIONS.UPDATE],
},
{
path: '/permissions/detail',
permissions: [PERMISSIONS.PERMISSIONS.READ_DETAIL],
},
];
//TODO : Fix this later
// const redirectToFirstAccessibleRoute = (userPermissions: string[]) => {
// const fallback = mappingRoutePermissions.find((route) =>
// route.permissions.some((perm) => userPermissions.includes(perm))
// );
// return redirect(fallback?.path ?? '/auth/login');
// };
export const middleware = async ({ request }: LoaderFunctionArgs) => { export const middleware = async ({ request }: LoaderFunctionArgs) => {
const url = new URL(request.url); const url = new URL(request.url);
const pathname = url.pathname; const pathname = url.pathname;
const session = SessionUser.get();
const session_token = SessionToken.get();
const token = session_token?.token?.access_token;
const userPermissions =
session?.role?.permissions?.map?.((perm) => perm?.name) ?? [];
if (pathname) return null; if (mappingPublicRoutes.includes(pathname)) {
if (token) return redirect('/dashboard');
return null;
}
if (!session) return redirect('/auth/login');
const matchedRoute = mappingRoutePermissions.find(
(route) => route.path === pathname
);
if (matchedRoute) {
const hasPermission =
!matchedRoute.permissions ||
matchedRoute.permissions.some((perm) => userPermissions.includes(perm));
if (!hasPermission) {
return '/dashboard';
}
}
return null; return null;
}; };
+1
View File
@@ -0,0 +1 @@
VITE_API_URL=
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Some files were not shown because too many files have changed in this diff Show More