diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..591229f8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true +max_line_length = 300 + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 92a30148..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "next/core-web-vitals", - "rules": { - "@next/next/no-img-element": "off" - } -} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..dfe07704 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore index 8f322f0d..943bef2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +# See https://help.github.com/ignore-files/ for more about ignoring files. + +.sass-cache +.vscode # dependencies /node_modules -/.pnp -.pnp.js +package-lock.json # testing /coverage @@ -11,25 +13,23 @@ # next.js /.next/ /out/ +tsconfig.tsbuildinfo # production /build +/idea +/.idea # misc .DS_Store -*.pem +.env.local +.env.development.local +.env.test.local +.env.production.local -# debug npm-debug.log* yarn-debug.log* yarn-error.log* -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts +layout.css +pages.css diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 9fec8807..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,33 +0,0 @@ -# Changelog - -## 10.0.0 - -- Upgrade to Next 13.4.8 -- Migrate to Next App Roter -- Migrate to PrimeReactContext -- Update to PrimeReact 9.6.2 -- Update other dependencies - -## 9.1.2 - -- Refactored project files - -## 9.1.1 - -- Fixed hydration warnings - -## 9.1.0 - -- Add typescript support - -## 9.0.0 - -- Upgrade PrimeReact to v9 -- Upgrade to PrimeReact 9.2.2 -- Upgrade to PrimeFlex 3.3.0 -- Upgrade to Next 13.2.3 -- Update other dependencies - -## 8.1.0 - -- Migrate CRA to NextJS diff --git a/README.md b/README.md index b2e3085d..b12f3e33 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,21 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next ## Getting Started -Sakai is an application template for Next.js based on the popular Next.js framework with new App Router. - First, run the development server: ```bash npm run dev # or yarn dev -# or -pnpm dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -## Integration with Existing Next.js Applications +You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. -Only the folders related to the layout need to be moved into your project. Integration of pages involves moving the files under those folders. Make sure that the using page is defined under the related group layout. +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. ## Learn More @@ -33,4 +31,4 @@ You can check out [the Next.js GitHub repository](https://github.com/vercel/next The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. \ No newline at end of file +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/app/(full-page)/layout.tsx b/app/(full-page)/layout.tsx deleted file mode 100644 index 7d5747fe..00000000 --- a/app/(full-page)/layout.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Metadata } from 'next'; -import AppConfig from '../../layout/AppConfig'; -import React from 'react'; - -interface SimpleLayoutProps { - children: React.ReactNode; -} - -export const metadata: Metadata = { - title: 'PrimeReact Sakai', - description: 'The ultimate collection of design-agnostic, flexible and accessible React UI Components.' -}; - -export default function SimpleLayout({ children }: SimpleLayoutProps) { - return ( - - {children} - - - ); -} diff --git a/app/(full-page)/pages/notfound/page.tsx b/app/(full-page)/pages/notfound/page.tsx deleted file mode 100644 index 52c0b4ce..00000000 --- a/app/(full-page)/pages/notfound/page.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import Link from 'next/link'; - -const NotFoundPage = () => { - return ( -
-
- Sakai logo -
-
- 404 -

Not Found

-
Requested resource is not available
- - - - - - Frequently Asked Questions - Ultricies mi quis hendrerit dolor. - - - - - - - - Solution Center - Phasellus faucibus scelerisque eleifend. - - - - - - - - Permission Manager - Accumsan in nisl nisi scelerisque - - -
-
-
-
- ); -}; - -export default NotFoundPage; diff --git a/app/(main)/documentation/page.tsx b/app/(main)/documentation/page.tsx deleted file mode 100644 index 404e5d2c..00000000 --- a/app/(main)/documentation/page.tsx +++ /dev/null @@ -1,244 +0,0 @@ -/* eslint-disable @next/next/no-sync-scripts */ -import React from 'react'; - -const Documentation = () => { - return ( - <> -
-
-
-

Current Version

-

Next v13, React v18 with PrimeReact v9

- -
Getting Started
-

- Sakai is an application template for React based on the popular{' '} - - NextJS - {' '} - framework with new{' '} - - App Router - - . To get started, clone the{' '} - - repository - {' '} - from GitHub and install the dependencies with npm or yarn. -

-
-                            {`"npm install" or "yarn"`}
-                        
- -

- Next step is running the application using the start script and navigate to http://localhost:3000/ to view the application. That is it, you may now start with the development of your application using the Sakai - template. -

- -
-                            {`"npm run dev" or "yarn dev"`}
-                        
- -
Dependencies
-

Dependencies of Sakai are listed below and needs to be defined at package.json.

- -
-                            {`"primereact": "^9.6.2",                    //required: PrimeReact components
-"primeicons": "^6.0.1",                    //required: Icons
-"primeflex": "^3.3.0",                     //required: Utility CSS classes
-`}
-                        
- -
Structure
-

Sakai consist of a couple of folders where demos and core layout have been separated.

-

- There are two{' '} - - root groups - {' '} - under the app folder; {`(main)`} represents the pages that reside in the main dashboard layout whereas {`(full-page)`}{' '} - groups the pages with full page content such as landing page or a login page. -

-
    -
  • - layout/: Main layout files -
  • -
  • - demo/: Contains demo related utilities and helpers -
  • -
  • - app/: Demo pages -
  • -
  • - public/demo: Assets used in demos -
  • -
  • - public/layout: Assets used in layout such as a logo -
  • -
  • - styles/demo: Styles used in demos only -
  • -
  • - styles/layout: SCSS files of the core layout -
  • -
-
Route Groups
-

- Root Layout is the main of the application and it is defined at app/layout.tsx file. It contains the style imports and layout context provider. -

-
-                            
-                                {`"use client"
-import { LayoutProvider } from "./layout/context/layoutcontext";
-import { PrimeReactProvider } from "primereact/api";
-import "primereact/resources/primereact.css";
-...
-import "../styles/layout/layout.scss";
-import "../styles/demo/Demos.scss";
-
-interface RootLayoutProps {
-  children: React.ReactNode;
-}
-
-export default function RootLayout({ children }: RootLayoutProps) {
-  return (
-    
-      
-        
-      
-      
-        
-            {children}
-        
-      
-    
-  );
-}
-
-`}
-                            
-                        
-

- The pages that are using the layout elements need to be defined under the app/{'(main)'}/ folder. Those pages use the{' '} - app/{'(main)'}/layout.tsx as the root layout. -

-
-                            
-                                {`import { Metadata } from 'next';
-import Layout from "../../layout/layout";
-
-interface MainLayoutProps {
-  children: React.ReactNode;
-}
-
-export const metadata: Metadata = {
-    title: "Sakai by PrimeReact | Free Admin Template for NextJS",
-    ...
-  };
-
-export default function MainLayout({ children }: MainLayoutProps) {
-  return {children};
-}
-`}
-                            
-                        
-

- Only the pages that are using config sidebar wihout layout elements need to be defined under the app/{'(full-page)'}/ folder. Those pages use the{' '} - app/{'(full-page)'}/layout.tsx as the root layout. -

-
-                            
-                                {`import { Metadata } from 'next';
-import AppConfig from "../../layout/AppConfig";
-import React from "react";
-
-interface FullPageLayoutProps {
-  children: React.ReactNode;
-}
-
-export const metadata: Metadata = {
-    title: "Sakai by PrimeReact | Free Admin Template for NextJS",
-    ...
-  };
-
-export default function FullPageLayout({ children }: FullPageLayoutProps) {
-  return (
-    
-      {children}
-      
-    
-  );
-}
-`}
-                            
-                        
-
Default Configuration
-

- Initial layout configuration can be defined at the layout/context/layoutcontext.js file, this step is optional and only necessary when customizing the defaults. -

- -
-                            
-                                {`"use client";
-import React, { useState } from 'react';
-import Head from 'next/head';
-export const LayoutContext = React.createContext();
-
-export const LayoutProvider = (props) => {
-    const [layoutConfig, setLayoutConfig] = useState({
-        ripple: false,                          //toggles ripple on and off
-        inputStyle: 'outlined',                 //default style for input elements
-        menuMode: 'static',                     //layout mode of the menu, valid values are "static" or "overlay"
-        colorScheme: 'light',                   //color scheme of the template, valid values are "light", "dim" and "dark"
-        theme: 'lara-light-indigo',             //default component theme for PrimeReact
-        scale: 14                               //size of the body font size to scale the whole application
-    });
-}`}
-                            
-                        
- -
Menu
-

- Main menu is defined at AppMenu.js file based on{' '} - - MenuModel API - - . -

- -
Integration with Existing NextJS Applications
-

Only the folders related to the layout need to be moved into your project. Integration of pages involves moving the files under those folders. Make sure that the using page is defined under the related group layout.

- -
PrimeReact Theme
-

- Sakai theming is based on the PrimeReact theme being used. Default theme is lara-light-indigo. -

- -
SASS Variables
-

- In case you'd like to customize the main layout variables, open _variables.scss file under layout folder. Saving the changes will be reflected instantly at your browser. -

- -
layout/_variables.scss
-
-                            
-                                {`
-/* General */
-$scale:14px;                    /* initial font size */ 
-$borderRadius:12px;             /* border radius of layout element e.g. card, sidebar */ 
-$transitionDuration:.2s;        /* transition duration of layout elements e.g. sidebar */ 
-`}
-                            
-                        
-
-
-
- - ); -}; - -export default Documentation; diff --git a/app/(main)/layout.tsx b/app/(main)/layout.tsx deleted file mode 100644 index 5cb39fdb..00000000 --- a/app/(main)/layout.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Metadata } from 'next'; -import Layout from '../../layout/layout'; - -interface AppLayoutProps { - children: React.ReactNode; -} - -export const metadata: Metadata = { - title: 'PrimeReact Sakai', - description: 'The ultimate collection of design-agnostic, flexible and accessible React UI Components.', - robots: { index: false, follow: false }, - viewport: { initialScale: 1, width: 'device-width' }, - openGraph: { - type: 'website', - title: 'PrimeReact SAKAI-REACT', - url: 'https://sakai.primereact.org/', - description: 'The ultimate collection of design-agnostic, flexible and accessible React UI Components.', - images: ['https://www.primefaces.org/static/social/sakai-react.png'], - ttl: 604800 - }, - icons: { - icon: '/favicon.ico' - } -}; - -export default function AppLayout({ children }: AppLayoutProps) { - return {children}; -} diff --git a/app/(main)/uikit/file/page.tsx b/app/(main)/uikit/file/page.tsx deleted file mode 100644 index 9dd41f9b..00000000 --- a/app/(main)/uikit/file/page.tsx +++ /dev/null @@ -1,35 +0,0 @@ -'use client'; - -import React, { useRef } from 'react'; -import { FileUpload } from 'primereact/fileupload'; -import { Toast } from 'primereact/toast'; - -const FileDemo = () => { - const toast = useRef(null); - - const onUpload = () => { - toast.current?.show({ - severity: 'info', - summary: 'Success', - detail: 'File Uploaded', - life: 3000 - }); - }; - - return ( -
- -
-
-
Advanced
- - -
Basic
- -
-
-
- ); -}; - -export default FileDemo; diff --git a/app/(main)/uikit/invalidstate/page.tsx b/app/(main)/uikit/invalidstate/page.tsx deleted file mode 100644 index e1c6c5a2..00000000 --- a/app/(main)/uikit/invalidstate/page.tsx +++ /dev/null @@ -1,117 +0,0 @@ -'use client'; - -import React, { useState, useEffect } from 'react'; -import { InputText } from 'primereact/inputtext'; -import { InputTextarea } from 'primereact/inputtextarea'; -import { InputMask } from 'primereact/inputmask'; -import { InputNumber } from 'primereact/inputnumber'; -import { AutoComplete, AutoCompleteCompleteEvent } from 'primereact/autocomplete'; -import { Calendar, CalendarChangeEvent } from 'primereact/calendar'; -import { Chips } from 'primereact/chips'; -import { Dropdown } from 'primereact/dropdown'; -import { MultiSelect } from 'primereact/multiselect'; -import { Password } from 'primereact/password'; -import { CountryService } from '../../../../demo/service/CountryService'; -import type { Demo } from '../../../../types/types'; - -const InvalidStateDemo = () => { - const [countries, setCountries] = useState([]); - const [filteredCountries, setFilteredCountries] = useState([]); - const [value1, setValue1] = useState(''); - const [value2, setValue2] = useState(null); - const [value3, setValue3] = useState(null); - const [value4, setValue4] = useState([]); - const [value5, setValue5] = useState(''); - const [value6, setValue6] = useState(''); - const [value7, setValue7] = useState(0); - const [value8, setValue8] = useState(null); - const [value9, setValue9] = useState(null); - const [value10, setValue10] = useState(''); - - const cities = [ - { name: 'New York', code: 'NY' }, - { name: 'Rome', code: 'RM' }, - { name: 'London', code: 'LDN' }, - { name: 'Istanbul', code: 'IST' }, - { name: 'Paris', code: 'PRS' } - ]; - - useEffect(() => { - CountryService.getCountries().then((countries) => { - setCountries(countries); - }); - }, []); - - const searchCountry = (event: AutoCompleteCompleteEvent) => { - // in a real application, make a request to a remote url with the query and - // return filtered results, for demo we filter at client side - const filtered = []; - const query = event.query; - for (let i = 0; i < countries.length; i++) { - const country = countries[i]; - if (country.name.toLowerCase().indexOf(query.toLowerCase()) === 0) { - filtered.push(country); - } - } - setFilteredCountries(filtered); - }; - - const onCalendarChange = (e: CalendarChangeEvent) => { - setValue3(e.value!); - }; - - return ( -
-
Invalid State
-
-
-
- - setValue1(e.target.value)} className="p-invalid" /> -
-
- - setValue2(e.value)} suggestions={filteredCountries} completeMethod={searchCountry} field="name" className="p-invalid" /> -
-
- - -
-
- - setValue4(e.value ?? [])} className="p-invalid" /> -
-
- - setValue5(e.target.value)} className="p-invalid" /> -
-
- -
-
- - setValue6(e.value ?? '')} className="p-invalid" /> -
-
- - setValue7(e.target.value ?? 0)} className="p-invalid" /> -
-
- - setValue8(e.value)} optionLabel="name" className="p-invalid" /> -
-
- - setValue9(e.value)} optionLabel="name" className="p-invalid" /> -
-
- - setValue10(e.target.value)} className="p-invalid" /> -
-
-
-
- ); -}; - -export default InvalidStateDemo; diff --git a/app/(main)/uikit/tree/page.tsx b/app/(main)/uikit/tree/page.tsx deleted file mode 100644 index cc93deb2..00000000 --- a/app/(main)/uikit/tree/page.tsx +++ /dev/null @@ -1,42 +0,0 @@ -'use client'; -import React, { useState, useEffect } from 'react'; -import { Tree, TreeCheckboxSelectionKeys, TreeMultipleSelectionKeys } from 'primereact/tree'; -import { TreeTable, TreeTableSelectionKeysType } from 'primereact/treetable'; -import { Column } from 'primereact/column'; -import { NodeService } from '../../../../demo/service/NodeService'; -import { TreeNode } from 'primereact/treenode'; - -const TreeDemo = () => { - const [files, setFiles] = useState([]); - const [files2, setFiles2] = useState([]); - const [selectedFileKeys, setSelectedFileKeys] = useState(null); - const [selectedFileKeys2, setSelectedFileKeys2] = useState(null); - - useEffect(() => { - NodeService.getFiles().then((files) => setFiles(files)); - NodeService.getFilesystem().then((files) => setFiles2(files)); - }, []); - - return ( -
-
-
-
Tree
- setSelectedFileKeys(e.value)} /> -
-
-
-
-
TreeTable
- setSelectedFileKeys2(e.value)}> - - - - -
-
-
- ); -}; - -export default TreeDemo; diff --git a/app/(main)/utilities/icons/page.tsx b/app/(main)/utilities/icons/page.tsx deleted file mode 100644 index a33d0c44..00000000 --- a/app/(main)/utilities/icons/page.tsx +++ /dev/null @@ -1,121 +0,0 @@ -'use client'; -import React, { useEffect, useState } from 'react'; -import Link from 'next/link'; -import { IconService } from '../../../../demo/service/IconService'; -import { InputText } from 'primereact/inputtext'; -import type { Demo } from '../../../../types/types'; - -const IconsDemo = () => { - const [icons, setIcons] = useState([]); - const [filteredIcons, setFilteredIcons] = useState([]); - - useEffect(() => { - IconService.getIcons().then((data) => { - data.sort((icon1, icon2) => { - if (icon1.properties!.name < icon2.properties!.name) return -1; - else if (icon1.properties!.name < icon2.properties!.name) return 1; - else return 0; - }); - - setIcons(data); - setFilteredIcons(data); - }); - }, []); - - const onFilter = (event: React.FormEvent) => { - if (!event.currentTarget.value) { - setFilteredIcons(icons); - } else { - setFilteredIcons( - icons.filter((it) => { - return it.icon && it.icon.tags && it.icon.tags[0].includes(event.currentTarget.value); - }) - ); - } - }; - - return ( -
-

Icons

-

- PrimeReact components internally use{' '} - - PrimeIcons - {' '} - library, the official icons suite from{' '} - - PrimeTek - - . -

-

Download

-

PrimeIcons is available at npm, run the following command to download it to your project.

-
-                {`npm install primeicons --save`}
-            
-

Getting Started

-

- PrimeIcons use the pi pi-{icon} syntax such as pi pi-check. A standalone icon can be displayed using an element like i or span -

-
-                
-                    {`
-`}
-                
-            
-

Size

-

Size of the icons can easily be changed using font-size property.

-
-                
-                    {`
-
-`}
-                
-            
- - -
-                
-                    {`
-
-`}
-                
-            
- -

Spinning Animation

-

Special pi-spin class applies continuous rotation to an icon.

-
-                {``}
-            
- -

List of Icons

-

- Here is the current list of PrimeIcons, more icons are added periodically. You may also{' '} - - request new icons - {' '} - at the issue tracker. -

-
- -
-
- {filteredIcons && - filteredIcons.map((iconMeta) => { - const { icon, properties } = iconMeta; - - return ( - icon?.tags?.indexOf('deprecate') === -1 && ( -
- -
pi-{properties?.name}
-
- ) - ); - })} -
-
- ); -}; - -export default IconsDemo; diff --git a/app/api/upload.ts b/app/api/upload.ts deleted file mode 100644 index 14c05b06..00000000 --- a/app/api/upload.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default function handler(req: any, res: any) { - res.status(200).setHeader('Access-Control-Allow-Origin', '*').json({ name: 'Fake Upload Process' }); -} diff --git a/app/layout.tsx b/app/layout.tsx deleted file mode 100644 index 4114afcf..00000000 --- a/app/layout.tsx +++ /dev/null @@ -1,27 +0,0 @@ -'use client'; -import { LayoutProvider } from '../layout/context/layoutcontext'; -import { PrimeReactProvider } from 'primereact/api'; -import 'primereact/resources/primereact.css'; -import 'primeflex/primeflex.css'; -import 'primeicons/primeicons.css'; -import '../styles/layout/layout.scss'; -import '../styles/demo/Demos.scss'; - -interface RootLayoutProps { - children: React.ReactNode; -} - -export default function RootLayout({ children }: RootLayoutProps) { - return ( - - - - - - - {children} - - - - ); -} diff --git a/demo/components/BlockViewer.tsx b/demo/components/BlockViewer.js similarity index 66% rename from demo/components/BlockViewer.tsx rename to demo/components/BlockViewer.js index bb69a511..481efd1b 100644 --- a/demo/components/BlockViewer.tsx +++ b/demo/components/BlockViewer.js @@ -1,22 +1,13 @@ import { Tooltip } from 'primereact/tooltip'; import { classNames } from 'primereact/utils'; import React, { useRef, useState } from 'react'; +import { CodeHighlight } from './CodeHighlight'; -interface BlockViewerProps { - header: string; - code: string; - new?: boolean; - free?: boolean; - containerClassName?: string; - previewStyle?: React.CSSProperties; - children: React.ReactNode; -} - -const BlockViewer = (props: BlockViewerProps) => { +const BlockViewer = (props) => { const [blockView, setBlockView] = useState('PREVIEW'); const actionCopyRef = useRef(null); - const copyCode = async (event: React.MouseEvent) => { + const copyCode = async (event) => { await navigator.clipboard.writeText(props.code); event.preventDefault(); }; @@ -28,19 +19,18 @@ const BlockViewer = (props: BlockViewerProps) => { {props.header} {props.new && New} - {props.free && Free}
- - - +
@@ -50,11 +40,7 @@ const BlockViewer = (props: BlockViewerProps) => {
)} - {blockView === 'CODE' && ( -
-                            {props.code}
-                        
- )} + {blockView === 'CODE' && {props.code}} diff --git a/demo/components/CodeHighlight.js b/demo/components/CodeHighlight.js new file mode 100644 index 00000000..263348c2 --- /dev/null +++ b/demo/components/CodeHighlight.js @@ -0,0 +1,9 @@ +import React from 'react'; + +export function CodeHighlight(props) { + return ( +
+            {props.children}
+        
+ ); +} diff --git a/demo/service/CountryService.js b/demo/service/CountryService.js new file mode 100644 index 00000000..b00f8070 --- /dev/null +++ b/demo/service/CountryService.js @@ -0,0 +1,13 @@ +import getConfig from 'next/config'; + +export class CountryService { + constructor() { + this.contextPath = getConfig().publicRuntimeConfig.contextPath; + } + + getCountries() { + return fetch(this.contextPath + '/demo/data/countries.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.data); + } +} diff --git a/demo/service/CountryService.tsx b/demo/service/CountryService.tsx deleted file mode 100644 index e3dbb2f1..00000000 --- a/demo/service/CountryService.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Demo } from '../../types/types'; - -export const CountryService = { - getCountries() { - return fetch('/demo/data/countries.json', { headers: { 'Cache-Control': 'no-cache' } }) - .then((res) => res.json()) - .then((d) => d.data as Demo.Country[]); - } -}; diff --git a/demo/service/CustomerService.js b/demo/service/CustomerService.js new file mode 100644 index 00000000..72ca9c4d --- /dev/null +++ b/demo/service/CustomerService.js @@ -0,0 +1,19 @@ +import getConfig from 'next/config'; + +export class CustomerService { + constructor() { + this.contextPath = getConfig().publicRuntimeConfig.contextPath; + } + + getCustomersMedium() { + return fetch(this.contextPath + '/demo/data/customers-medium.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.data); + } + + getCustomersLarge() { + return fetch(this.contextPath + '/demo/data/customers-large.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.data); + } +} diff --git a/demo/service/CustomerService.tsx b/demo/service/CustomerService.tsx deleted file mode 100644 index f962123e..00000000 --- a/demo/service/CustomerService.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Demo } from '../../types/types'; - -export const CustomerService = { - getCustomersMedium() { - return fetch('/demo/data/customers-medium.json', { headers: { 'Cache-Control': 'no-cache' } }) - .then((res) => res.json()) - .then((d) => d.data as Demo.Customer[]); - }, - - getCustomersLarge() { - return fetch('/demo/data/customers-large.json', { headers: { 'Cache-Control': 'no-cache' } }) - .then((res) => res.json()) - .then((d) => d.data as Demo.Customer[]); - } -}; diff --git a/demo/service/EventService.js b/demo/service/EventService.js new file mode 100644 index 00000000..52683df0 --- /dev/null +++ b/demo/service/EventService.js @@ -0,0 +1,13 @@ +import getConfig from 'next/config'; + +export class EventService { + constructor() { + this.contextPath = getConfig().publicRuntimeConfig.contextPath; + } + + getEvents() { + return fetch('/demo/data/events.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.data); + } +} diff --git a/demo/service/EventService.tsx b/demo/service/EventService.tsx deleted file mode 100644 index 58e8ebdd..00000000 --- a/demo/service/EventService.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Demo } from '../../types/types'; - -export const EventService = { - getEvents() { - return fetch('/demo/data/events.json', { headers: { 'Cache-Control': 'no-cache' } }) - .then((res) => res.json()) - .then((d) => d.data as Demo.Event); - } -}; diff --git a/demo/service/IconService.js b/demo/service/IconService.js new file mode 100644 index 00000000..d951099b --- /dev/null +++ b/demo/service/IconService.js @@ -0,0 +1,22 @@ +import getConfig from 'next/config'; + +export class IconService { + constructor() { + this.icons = []; + this.selectedIcon = null; + this.contextPath = getConfig().publicRuntimeConfig.contextPath; + } + + getIcons() { + return fetch(this.contextPath + '/demo/data/icons.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.icons); + } + + getIcon(id) { + if (this.icons) { + this.selectedIcon = this.icons.find((x) => x.properties.id === id); + return this.selectedIcon; + } + } +} diff --git a/demo/service/IconService.tsx b/demo/service/IconService.tsx deleted file mode 100644 index 1bb0c856..00000000 --- a/demo/service/IconService.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Demo } from '../../types/types'; - -let icons: Demo.Icon[] = []; -let selectedIcon: Demo.Icon | undefined; -export const IconService = { - getIcons() { - return fetch('/demo/data/icons.json', { headers: { 'Cache-Control': 'no-cache' } }) - .then((res) => res.json()) - .then((d) => d.icons as Demo.Icon[]); - }, - - getIcon(id: number) { - if (icons) { - selectedIcon = icons.find((x: Demo.Icon) => x.properties?.id === id); - return selectedIcon; - } - } -}; diff --git a/demo/service/NodeService.js b/demo/service/NodeService.js new file mode 100644 index 00000000..b0f40d02 --- /dev/null +++ b/demo/service/NodeService.js @@ -0,0 +1,19 @@ +import getConfig from 'next/config'; + +export class NodeService { + constructor() { + this.contextPath = getConfig().publicRuntimeConfig.contextPath; + } + + getTreeNodes() { + return fetch(this.contextPath + '/demo/data/treenodes.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.root); + } + + getTreeTableNodes() { + return fetch(this.contextPath + '/demo/data/treetablenodes.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.root); + } +} diff --git a/demo/service/NodeService.tsx b/demo/service/NodeService.tsx deleted file mode 100644 index f30d3209..00000000 --- a/demo/service/NodeService.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { TreeNode } from 'primereact/treenode'; - -export const NodeService = { - getFiles() { - return fetch('/demo/data/files.json', { - headers: { 'Cache-Control': 'no-cache' } - }) - .then((res) => res.json()) - .then((d) => d.data as TreeNode[]); - }, - - getLazyFiles() { - return fetch('/demo/data/files-lazy.json', { - headers: { 'Cache-Control': 'no-cache' } - }) - .then((res) => res.json()) - .then((d) => d.data as TreeNode[]); - }, - - getFilesystem() { - return fetch('/demo/data/filesystem.json', { - headers: { 'Cache-Control': 'no-cache' } - }) - .then((res) => res.json()) - .then((d) => d.data as TreeNode[]); - }, - - getLazyFilesystem() { - return fetch('/demo/data/filesystem-lazy.json', { - headers: { 'Cache-Control': 'no-cache' } - }) - .then((res) => res.json()) - .then((d) => d.data as TreeNode[]); - } -}; diff --git a/demo/service/PhotoService.js b/demo/service/PhotoService.js new file mode 100644 index 00000000..a8fb64b8 --- /dev/null +++ b/demo/service/PhotoService.js @@ -0,0 +1,13 @@ +import getConfig from 'next/config'; + +export class PhotoService { + constructor() { + this.contextPath = getConfig().publicRuntimeConfig.contextPath; + } + + getImages() { + return fetch(this.contextPath + '/demo/data/photos.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.data); + } +} diff --git a/demo/service/PhotoService.tsx b/demo/service/PhotoService.tsx deleted file mode 100644 index b4dec9c9..00000000 --- a/demo/service/PhotoService.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Demo } from '../../types/types'; - -export const PhotoService = { - getImages() { - return fetch('/demo/data/photos.json', { headers: { 'Cache-Control': 'no-cache' } }) - .then((res) => res.json()) - .then((d) => d.data as Demo.Photo[]); - } -}; diff --git a/demo/service/ProductService.js b/demo/service/ProductService.js new file mode 100644 index 00000000..36728215 --- /dev/null +++ b/demo/service/ProductService.js @@ -0,0 +1,25 @@ +import getConfig from 'next/config'; + +export class ProductService { + constructor() { + this.contextPath = getConfig().publicRuntimeConfig.contextPath; + } + + getProductsSmall() { + return fetch(this.contextPath + '/demo/data/products-small.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.data); + } + + getProducts() { + return fetch(this.contextPath + '/demo/data/products.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.data); + } + + getProductsWithOrdersSmall() { + return fetch(this.contextPath + '/demo/data/products-orders-small.json', { headers: { 'Cache-Control': 'no-cache' } }) + .then((res) => res.json()) + .then((d) => d.data); + } +} diff --git a/demo/service/ProductService.tsx b/demo/service/ProductService.tsx deleted file mode 100644 index 4d0180c8..00000000 --- a/demo/service/ProductService.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Demo } from '../../types/types'; - -export const ProductService = { - getProductsSmall() { - return fetch('/demo/data/products-small.json', { headers: { 'Cache-Control': 'no-cache' } }) - .then((res) => res.json()) - .then((d) => d.data as Demo.Product[]); - }, - - getProducts() { - return fetch('/demo/data/products.json', { headers: { 'Cache-Control': 'no-cache' } }) - .then((res) => res.json()) - .then((d) => d.data as Demo.Product[]); - }, - - getProductsWithOrdersSmall() { - return fetch('/demo/data/products-orders-small.json', { headers: { 'Cache-Control': 'no-cache' } }) - .then((res) => res.json()) - .then((d) => d.data as Demo.Product[]); - } -}; diff --git a/demo/utils/ScrollToTop.js b/demo/utils/ScrollToTop.js new file mode 100644 index 00000000..50ab92fd --- /dev/null +++ b/demo/utils/ScrollToTop.js @@ -0,0 +1,14 @@ +import { useEffect } from 'react'; +import { useRouter, withRouter } from 'next/router'; + +function ScrollToTop(props) { + const router = useRouter(); + + // useEffect(() => { + // window.scrollTo(0, 0) + // }, [router]); + + return props.children; +} + +export default withRouter(ScrollToTop); diff --git a/demo/utils/navlink.js b/demo/utils/navlink.js new file mode 100644 index 00000000..83538afa --- /dev/null +++ b/demo/utils/navlink.js @@ -0,0 +1,33 @@ +import { useRouter } from 'next/router'; +import Link from 'next/link'; +import PropTypes from 'prop-types'; + +export { NavLink }; + +NavLink.propTypes = { + href: PropTypes.string.isRequired, + activeclassname: PropTypes.string, + exact: PropTypes.bool, + role: PropTypes.string +}; + +NavLink.defaultProps = { + exact: false +}; + +function NavLink({ href, exact, children, role, target, ariaLabel, ...props }) { + const { pathname } = useRouter(); + const isActive = exact ? pathname === href : pathname.startsWith(href); + + if (isActive) { + props.className += ' active-route'; + } + + return ( + + + {children} + + + ); +} diff --git a/demo/utils/serviceWorker.js b/demo/utils/serviceWorker.js new file mode 100644 index 00000000..69abc8b9 --- /dev/null +++ b/demo/utils/serviceWorker.js @@ -0,0 +1,122 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read http://bit.ly/CRA-PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.1/8 is considered localhost for IPv4. + window.location.hostname?.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/) +); + +export function register(config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log('This web app is being served cache-first by a service ' + 'worker. To learn more, visit http://bit.ly/CRA-PWA'); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl, config) { + navigator.serviceWorker + .register(swUrl) + .then((registration) => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log('New content is available and will be used when all ' + 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'); + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch((error) => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl, config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl) + .then((response) => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); + if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then((registration) => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log('No internet connection found. App is running in offline mode.'); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready.then((registration) => { + registration.unregister(); + }); + } +} diff --git a/layout/AppConfig.js b/layout/AppConfig.js new file mode 100644 index 00000000..1f28261c --- /dev/null +++ b/layout/AppConfig.js @@ -0,0 +1,339 @@ +import getConfig from 'next/config'; +import PrimeReact from 'primereact/api'; +import { Button } from 'primereact/button'; +import { InputSwitch } from 'primereact/inputswitch'; +import { RadioButton } from 'primereact/radiobutton'; +import { Sidebar } from 'primereact/sidebar'; +import { classNames } from 'primereact/utils'; +import React, { useContext, useEffect, useState } from 'react'; +import { LayoutContext } from './context/layoutcontext'; + +const AppConfig = (props) => { + const [scales] = useState([12, 13, 14, 15, 16]); + const { layoutConfig, setLayoutConfig, layoutState, setLayoutState } = useContext(LayoutContext); + const contextPath = getConfig().publicRuntimeConfig.contextPath; + + const onConfigButtonClick = () => { + setLayoutState((prevState) => ({ ...prevState, configSidebarVisible: true })); + }; + + const onConfigSidebarHide = () => { + setLayoutState((prevState) => ({ ...prevState, configSidebarVisible: false })); + }; + + const changeInputStyle = (e) => { + setLayoutConfig((prevState) => ({ ...prevState, inputStyle: e.value })); + }; + + const changeRipple = (e) => { + PrimeReact.ripple = e.value; + setLayoutConfig((prevState) => ({ ...prevState, ripple: e.value })); + }; + + const changeMenuMode = (e) => { + setLayoutConfig((prevState) => ({ ...prevState, menuMode: e.value })); + }; + + const changeTheme = (theme, colorScheme) => { + const themeLink = document.getElementById('theme-css'); + const themeHref = themeLink ? themeLink.getAttribute('href') : null; + const newHref = themeHref ? themeHref.replace(layoutConfig.theme, theme) : null; + + replaceLink(themeLink, newHref, () => { + setLayoutConfig((prevState) => ({ ...prevState, theme, colorScheme })); + }); + }; + + const replaceLink = (linkElement, href, onComplete) => { + if (!linkElement || !href) { + return; + } + + const id = linkElement.getAttribute('id'); + const cloneLinkElement = linkElement.cloneNode(true); + + cloneLinkElement.setAttribute('href', href); + cloneLinkElement.setAttribute('id', id + '-clone'); + + linkElement.parentNode.insertBefore(cloneLinkElement, linkElement.nextSibling); + + cloneLinkElement.addEventListener('load', () => { + linkElement.remove(); + + const element = document.getElementById(id); // re-check + element && element.remove(); + + cloneLinkElement.setAttribute('id', id); + onComplete && onComplete(); + }); + }; + + const decrementScale = () => { + setLayoutConfig((prevState) => ({ ...prevState, scale: prevState.scale - 1 })); + }; + + const incrementScale = () => { + setLayoutConfig((prevState) => ({ ...prevState, scale: prevState.scale + 1 })); + }; + + const applyScale = () => { + document.documentElement.style.fontSize = layoutConfig.scale + 'px'; + }; + + + useEffect(() => { + applyScale(); + }, [layoutConfig.scale]); + + return ( + <> + + + +
Scale
+
+ +
+ {scales.map((item) => { + return ; + })} +
+ +
+ + { !props.simple && + <> +
Menu Type
+
+
+ changeMenuMode(e)} inputId="mode1"> + +
+
+ changeMenuMode(e)} inputId="mode2"> + +
+
+ + } + +
Input Style
+
+
+ changeInputStyle(e)} inputId="outlined_input"> + +
+
+ changeInputStyle(e)} inputId="filled_input"> + +
+
+ +
Ripple Effect
+ changeRipple(e)}> + +
Bootstrap
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
Material Design
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
Material Design Compact
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
Tailwind
+
+
+ +
+
+ +
Fluent UI
+
+
+ +
+
+ +
PrimeOne Design - 2022
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
PrimeOne Design - 2021
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + ); +}; + +export default AppConfig; diff --git a/layout/AppConfig.tsx b/layout/AppConfig.tsx deleted file mode 100644 index 97576356..00000000 --- a/layout/AppConfig.tsx +++ /dev/null @@ -1,314 +0,0 @@ -"use client"; - -import { PrimeReactContext } from 'primereact/api'; -import { Button } from 'primereact/button'; -import { InputSwitch, InputSwitchChangeEvent } from 'primereact/inputswitch'; -import { RadioButton, RadioButtonChangeEvent } from 'primereact/radiobutton'; -import { Sidebar } from 'primereact/sidebar'; -import { classNames } from 'primereact/utils'; -import React, { useContext, useEffect, useState } from 'react'; -import { AppConfigProps, LayoutConfig, LayoutState } from '../types/types'; -import { LayoutContext } from './context/layoutcontext'; - -const AppConfig = (props: AppConfigProps) => { - const [scales] = useState([12, 13, 14, 15, 16]); - const { layoutConfig, setLayoutConfig, layoutState, setLayoutState } = useContext(LayoutContext); - const { setRipple, changeTheme } = useContext(PrimeReactContext); - - const onConfigButtonClick = () => { - setLayoutState((prevState: LayoutState) => ({ ...prevState, configSidebarVisible: true })); - }; - - const onConfigSidebarHide = () => { - setLayoutState((prevState: LayoutState) => ({ ...prevState, configSidebarVisible: false })); - }; - - const changeInputStyle = (e: RadioButtonChangeEvent) => { - setLayoutConfig((prevState: LayoutConfig) => ({ ...prevState, inputStyle: e.value })); - }; - - const changeRipple = (e: InputSwitchChangeEvent) => { - setRipple(e.value as boolean); - setLayoutConfig((prevState: LayoutConfig) => ({ ...prevState, ripple: e.value as boolean })); - }; - - const changeMenuMode = (e: RadioButtonChangeEvent) => { - setLayoutConfig((prevState: LayoutConfig) => ({ ...prevState, menuMode: e.value })); - }; - - const _changeTheme = (theme: string, colorScheme: string) => { - changeTheme?.(layoutConfig.theme, theme, 'theme-css', () => { - setLayoutConfig((prevState: LayoutConfig) => ({ ...prevState, theme, colorScheme })); - }); - }; - - const decrementScale = () => { - setLayoutConfig((prevState: LayoutConfig) => ({ ...prevState, scale: prevState.scale - 1 })); - }; - - const incrementScale = () => { - setLayoutConfig((prevState: LayoutConfig) => ({ ...prevState, scale: prevState.scale + 1 })); - }; - - const applyScale = () => { - document.documentElement.style.fontSize = layoutConfig.scale + 'px'; - }; - - useEffect(() => { - applyScale(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [layoutConfig.scale]); - - return ( - <> - - - - - - {!props.simple && ( - <> -
Scale
-
- -
- {scales.map((item) => { - return ; - })} -
- -
- -
Menu Type
-
-
- changeMenuMode(e)} inputId="mode1"> - -
-
- changeMenuMode(e)} inputId="mode2"> - -
-
- -
Input Style
-
-
- changeInputStyle(e)} inputId="outlined_input"> - -
-
- changeInputStyle(e)} inputId="filled_input"> - -
-
- -
Ripple Effect
- changeRipple(e)}> - - )} -
Bootstrap
-
-
- -
-
- -
-
- -
-
- -
-
- -
Material Design
-
-
- -
-
- -
-
- -
-
- -
-
- -
Material Design Compact
-
-
- -
-
- -
-
- -
-
- -
-
- -
Tailwind
-
-
- -
-
- -
Fluent UI
-
-
- -
-
- -
PrimeOne Design - 2022
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
PrimeOne Design - 2021
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
- - ); -}; - -export default AppConfig; diff --git a/layout/AppFooter.tsx b/layout/AppFooter.js similarity index 57% rename from layout/AppFooter.tsx rename to layout/AppFooter.js index 424b9987..143ea31a 100644 --- a/layout/AppFooter.tsx +++ b/layout/AppFooter.js @@ -1,14 +1,14 @@ -/* eslint-disable @next/next/no-img-element */ - +import getConfig from 'next/config'; import React, { useContext } from 'react'; import { LayoutContext } from './context/layoutcontext'; const AppFooter = () => { const { layoutConfig } = useContext(LayoutContext); + const contextPath = getConfig().publicRuntimeConfig.contextPath; return (
- Logo + Logo by PrimeReact
diff --git a/layout/AppMenu.tsx b/layout/AppMenu.js similarity index 89% rename from layout/AppMenu.tsx rename to layout/AppMenu.js index 306481b2..59bf9d87 100644 --- a/layout/AppMenu.tsx +++ b/layout/AppMenu.js @@ -1,16 +1,14 @@ -/* eslint-disable @next/next/no-img-element */ - +import getConfig from 'next/config'; import React, { useContext } from 'react'; import AppMenuitem from './AppMenuitem'; import { LayoutContext } from './context/layoutcontext'; import { MenuProvider } from './context/menucontext'; import Link from 'next/link'; -import { AppMenuItem } from '../types/types'; const AppMenu = () => { const { layoutConfig } = useContext(LayoutContext); - - const model: AppMenuItem[] = [ + const contextPath = getConfig().publicRuntimeConfig.contextPath; + const model = [ { label: 'Home', items: [{ label: 'Dashboard', icon: 'pi pi-fw pi-home', to: '/' }] @@ -40,14 +38,14 @@ const AppMenu = () => { label: 'Prime Blocks', items: [ { label: 'Free Blocks', icon: 'pi pi-fw pi-eye', to: '/blocks', badge: 'NEW' }, - { label: 'All Blocks', icon: 'pi pi-fw pi-globe', url: 'https://blocks.primereact.org', target: '_blank' } + { label: 'All Blocks', icon: 'pi pi-fw pi-globe', url: 'https://www.primefaces.org/primeblocks-react', target: '_blank' } ] }, { label: 'Utilities', items: [ { label: 'PrimeIcons', icon: 'pi pi-fw pi-prime', to: '/utilities/icons' }, - { label: 'PrimeFlex', icon: 'pi pi-fw pi-desktop', url: 'https://primeflex.org/', target: '_blank' } + { label: 'PrimeFlex', icon: 'pi pi-fw pi-desktop', url: 'https://www.primefaces.org/primeflex/', target: '_blank' } ] }, { @@ -116,7 +114,7 @@ const AppMenu = () => { items: [ { label: 'Submenu 1.1.1', icon: 'pi pi-fw pi-bookmark' }, { label: 'Submenu 1.1.2', icon: 'pi pi-fw pi-bookmark' }, - { label: 'Submenu 1.1.3', icon: 'pi pi-fw pi-bookmark' } + { label: 'Submenu 1.1.3', icon: 'pi pi-fw pi-bookmark' }, ] }, { @@ -169,11 +167,13 @@ const AppMenu = () => {
    {model.map((item, i) => { - return !item?.seperator ? :
  • ; + return !item.seperator ? :
  • ; })} - - Prime Blocks + + + Prime Blocks +
diff --git a/layout/AppMenuitem.js b/layout/AppMenuitem.js new file mode 100644 index 00000000..6b317561 --- /dev/null +++ b/layout/AppMenuitem.js @@ -0,0 +1,92 @@ +import { useRouter } from 'next/router'; +import Link from 'next/link'; +import { Ripple } from 'primereact/ripple'; +import { classNames } from 'primereact/utils'; +import React, { useEffect, useContext } from 'react'; +import { CSSTransition } from 'react-transition-group'; +import { MenuContext } from './context/menucontext'; + +const AppMenuitem = (props) => { + const { activeMenu, setActiveMenu } = useContext(MenuContext); + const router = useRouter(); + const item = props.item; + const key = props.parentKey ? props.parentKey + '-' + props.index : String(props.index); + const isActiveRoute = item.to && router.pathname === item.to; + const active = activeMenu === key || activeMenu.startsWith(key + '-'); + + useEffect(() => { + if (item.to && router.pathname === item.to) { + setActiveMenu(key); + } + + const onRouteChange = (url) => { + if (item.to && item.to === url) { + setActiveMenu(key); + } + }; + + router.events.on('routeChangeComplete', onRouteChange); + + return () => { + router.events.off('routeChangeComplete', onRouteChange); + }; + }, []); + + const itemClick = (event) => { + //avoid processing disabled items + if (item.disabled) { + event.preventDefault(); + return; + } + + //execute command + if (item.command) { + item.command({ originalEvent: event, item: item }); + } + + // toggle active state + if (item.items) + setActiveMenu(active ? props.parentKey : key); + else + setActiveMenu(key); + }; + + const subMenu = item.items && item.visible !== false && ( + +
    + {item.items.map((child, i) => { + return ; + })} +
+
+ ); + + return ( +
  • + {props.root && item.visible !== false &&
    {item.label}
    } + {(!item.to || item.items) && item.visible !== false ? ( + itemClick(e)} className={classNames(item.class, 'p-ripple')} target={item.target} tabIndex="0"> + + {item.label} + {item.items && } + + + ) : null} + + {item.to && !item.items && item.visible !== false ? ( + + itemClick(e)} className={classNames(item.class, 'p-ripple', { 'active-route': isActiveRoute })} target={item.target} tabIndex="0"> + + {item.label} + {item.items && } + + + + ) : null} + + {subMenu} +
  • + ); +}; + +export default AppMenuitem; diff --git a/layout/AppMenuitem.tsx b/layout/AppMenuitem.tsx deleted file mode 100644 index b9074cf6..00000000 --- a/layout/AppMenuitem.tsx +++ /dev/null @@ -1,86 +0,0 @@ -'use client' -import { useRouter } from 'next/navigation'; -import Link from 'next/link'; -import { Ripple } from 'primereact/ripple'; -import { classNames } from 'primereact/utils'; -import React, { useEffect, useContext } from 'react'; -import { CSSTransition } from 'react-transition-group'; -import { MenuContext } from './context/menucontext'; -import { AppMenuItemProps } from '../types/types'; -import { usePathname, useSearchParams } from 'next/navigation' - - -const AppMenuitem = (props: AppMenuItemProps) => { - const pathname = usePathname(); - const searchParams = useSearchParams(); - const { activeMenu, setActiveMenu } = useContext(MenuContext); - const item = props.item; - const key = props.parentKey ? props.parentKey + '-' + props.index : String(props.index); - const isActiveRoute = item!.to && pathname === item!.to; - const active = activeMenu === key || activeMenu.startsWith(key + '-'); - const onRouteChange = (url: string) => { - if (item!.to && item!.to === url) { - setActiveMenu(key); - } - }; - - - useEffect(() => { - onRouteChange(pathname); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [pathname, searchParams]); - - const itemClick = (event: React.MouseEvent) => { - //avoid processing disabled items - if (item!.disabled) { - event.preventDefault(); - return; - } - - //execute command - if (item!.command) { - item!.command({ originalEvent: event, item: item }); - } - - // toggle active state - if (item!.items) setActiveMenu(active ? (props.parentKey as string) : key); - else setActiveMenu(key); - }; - - const subMenu = item!.items && item!.visible !== false && ( - -
      - {item!.items.map((child, i) => { - return ; - })} -
    -
    - ); - - return ( -
  • - {props.root && item!.visible !== false &&
    {item!.label}
    } - {(!item!.to || item!.items) && item!.visible !== false ? ( - itemClick(e)} className={classNames(item!.class, 'p-ripple')} target={item!.target} tabIndex={0}> - - {item!.label} - {item!.items && } - - - ) : null} - - {item!.to && !item!.items && item!.visible !== false ? ( - itemClick(e)} className={classNames(item!.class, 'p-ripple', { 'active-route': isActiveRoute })} tabIndex={0}> - - {item!.label} - {item!.items && } - - - ) : null} - - {subMenu} -
  • - ); -}; - -export default AppMenuitem; diff --git a/layout/AppSidebar.js b/layout/AppSidebar.js new file mode 100644 index 00000000..8a4a0d37 --- /dev/null +++ b/layout/AppSidebar.js @@ -0,0 +1,9 @@ +import AppMenu from './AppMenu'; + +const AppSidebar = () => { + return ( + + ); +} + +export default AppSidebar; \ No newline at end of file diff --git a/layout/AppSidebar.tsx b/layout/AppSidebar.tsx deleted file mode 100644 index ec2ca424..00000000 --- a/layout/AppSidebar.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import AppMenu from './AppMenu'; - -const AppSidebar = () => { - return ; -}; - -export default AppSidebar; diff --git a/layout/AppTopbar.tsx b/layout/AppTopbar.js similarity index 77% rename from layout/AppTopbar.tsx rename to layout/AppTopbar.js index 1529f92b..4f32bcf8 100644 --- a/layout/AppTopbar.tsx +++ b/layout/AppTopbar.js @@ -1,16 +1,16 @@ -/* eslint-disable @next/next/no-img-element */ - +import getConfig from 'next/config'; import Link from 'next/link'; +import Router, { useRouter } from 'next/router'; import { classNames } from 'primereact/utils'; import React, { forwardRef, useContext, useImperativeHandle, useRef } from 'react'; -import { AppTopbarRef } from '../types/types'; import { LayoutContext } from './context/layoutcontext'; -const AppTopbar = forwardRef((props, ref) => { +const AppTopbar = forwardRef((props, ref) => { const { layoutConfig, layoutState, onMenuToggle, showProfileSidebar } = useContext(LayoutContext); const menubuttonRef = useRef(null); const topbarmenuRef = useRef(null); const topbarmenubuttonRef = useRef(null); + const contextPath = getConfig().publicRuntimeConfig.contextPath; useImperativeHandle(ref, () => ({ menubutton: menubuttonRef.current, @@ -20,9 +20,13 @@ const AppTopbar = forwardRef((props, ref) => { return (
    - - logo - SAKAI + + + <> + logo + SAKAI + +
    - + + ); +}; + +AccessDeniedPage.getLayout = function getLayout(page) { + return ( + + {page} + + ); }; diff --git a/app/(full-page)/auth/error/page.tsx b/pages/auth/error/index.js similarity index 56% rename from app/(full-page)/auth/error/page.tsx rename to pages/auth/error/index.js index bca51f31..c04076d5 100644 --- a/app/(full-page)/auth/error/page.tsx +++ b/pages/auth/error/index.js @@ -1,36 +1,40 @@ -/* eslint-disable @next/next/no-img-element */ -'use client'; -import { useRouter } from 'next/navigation'; +import getConfig from 'next/config'; +import { useRouter } from 'next/router'; import React from 'react'; +import AppConfig from '../../../layout/AppConfig'; import { Button } from 'primereact/button'; const ErrorPage = () => { + const contextPath = getConfig().publicRuntimeConfig.contextPath; const router = useRouter(); return (
    - Sakai logo -
    + Sakai logo +

    Error Occured

    Something went wrong.
    - Error -
    -
    +
    ); }; +ErrorPage.getLayout = function getLayout(page) { + return ( + + {page} + + + ); +} + export default ErrorPage; diff --git a/app/(full-page)/auth/login/page.tsx b/pages/auth/login/index.js similarity index 62% rename from app/(full-page)/auth/login/page.tsx rename to pages/auth/login/index.js index d3dd85ca..65fa5dec 100644 --- a/app/(full-page)/auth/login/page.tsx +++ b/pages/auth/login/index.js @@ -1,11 +1,11 @@ -/* eslint-disable @next/next/no-img-element */ -'use client'; -import { useRouter } from 'next/navigation'; +import getConfig from 'next/config'; +import { useRouter } from 'next/router'; import React, { useContext, useState } from 'react'; +import AppConfig from '../../../layout/AppConfig'; import { Checkbox } from 'primereact/checkbox'; import { Button } from 'primereact/button'; import { Password } from 'primereact/password'; -import { LayoutContext } from '../../../../layout/context/layoutcontext'; +import { LayoutContext } from '../../../layout/context/layoutcontext'; import { InputText } from 'primereact/inputtext'; import { classNames } from 'primereact/utils'; @@ -13,24 +13,18 @@ const LoginPage = () => { const [password, setPassword] = useState(''); const [checked, setChecked] = useState(false); const { layoutConfig } = useContext(LayoutContext); - + const contextPath = getConfig().publicRuntimeConfig.contextPath; const router = useRouter(); - const containerClassName = classNames('surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden', { 'p-input-filled': layoutConfig.inputStyle === 'filled' }); + const containerClassName = classNames('surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden', {'p-input-filled': layoutConfig.inputStyle === 'filled'}); return (
    - Sakai logo -
    + Sakai logo +
    - Image + Image
    Welcome, Isabel!
    Sign in to continue
    @@ -39,17 +33,19 @@ const LoginPage = () => { - + - setPassword(e.target.value)} placeholder="Password" toggleMask className="w-full mb-5" inputClassName="w-full p-3 md:w-30rem"> + setPassword(e.target.value)} placeholder="Password" toggleMask className="w-full mb-5" inputClassName='w-full p-3 md:w-30rem'>
    - setChecked(e.checked ?? false)} className="mr-2"> - + setChecked(e.checked)} className="mr-2"> +
    Forgot password? @@ -64,4 +60,12 @@ const LoginPage = () => { ); }; +LoginPage.getLayout = function getLayout(page) { + return ( + + {page} + + + ); +}; export default LoginPage; diff --git a/app/(main)/blocks/page.tsx b/pages/blocks/index.js similarity index 59% rename from app/(main)/blocks/page.tsx rename to pages/blocks/index.js index ebd5a25c..022828f2 100644 --- a/app/(main)/blocks/page.tsx +++ b/pages/blocks/index.js @@ -1,104 +1,104 @@ -'use client'; -import React, { useState } from 'react'; - -import { InputText } from 'primereact/inputtext'; -import { Chip } from 'primereact/chip'; -import { Checkbox } from 'primereact/checkbox'; +import getConfig from 'next/config'; import { Button } from 'primereact/button'; -import BlockViewer from '../../../demo/components/BlockViewer'; +import { Checkbox } from 'primereact/checkbox'; +import { Chip } from 'primereact/chip'; +import { InputText } from 'primereact/inputtext'; +import React, { useState } from 'react'; +import BlockViewer from '../../demo/components/BlockViewer'; -const Free = () => { +const BlocksDemo = () => { const [checked, setChecked] = useState(false); + const contextPath = getConfig().publicRuntimeConfig.contextPath; const block1 = ` -
    +
    - Create the screens + Create the screens your
    your visitors deserve to see

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

    - +
    - hero-1 + hero-1
    `; const block2 = ` -
    -
    +
    +
    One Product, Many Solutions
    -
    Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.
    +
    Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.
    - + -
    Built for Developers
    - Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. +
    Built for Developers
    + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
    - + -
    End-to-End Encryption
    - Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis. +
    End-to-End Encryption
    + Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis.
    - + -
    Easy to Use
    - Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper. +
    Easy to Use
    + Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper.
    - + -
    Fast & Global Support
    - Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus. +
    Fast & Global Support
    + Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus.
    - + -
    Open Source
    - Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat. +
    Open Source
    + Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat.
    - + -
    Trusted Securitty
    - Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend. +
    Trusted Securitty
    + Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend.
    `; const block3 = ` -
    +
    Pricing Plans
    Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.
    -
    +
    Basic
    Plan description
    -
    +
    $9 per month
    -
    +
    • @@ -113,23 +113,23 @@ const Free = () => { Morbi tincidunt augue
    -
    -
    -
    +
    Premium
    Plan description
    -
    +
    $29 per month
    -
    +
    • @@ -148,23 +148,23 @@ const Free = () => { Duis ultricies lacus sed
    -
    -
    -
    +
    Enterprise
    Plan description
    -
    +
    $49 per month
    -
    +
    • @@ -191,8 +191,8 @@ const Free = () => { Nisi scelerisque
    -
    -
    @@ -201,31 +201,33 @@ const Free = () => { `; const block4 = ` -
    -
     POWERED BY DISCORD
    -
    Join Our Design Community
    -
    Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.
    - +
    `; const block5 = `
    `; const block6 = ` -
    +
    • Application @@ -264,139 +266,139 @@ const Free = () => { `; const block7 = ` -
      -
      -
      -
      -
      - Orders -
      152
      -
      -
      - +
      +
      +
      +
      +
      +
      + Orders +
      152
      +
      +
      + +
      + 24 new + since last visit
      - 24 new - since last visit
      -
      -
      -
      -
      -
      - Revenue -
      $2.100
      -
      -
      - +
      +
      +
      +
      + Revenue +
      $2.100
      +
      +
      + +
      + %52+ + since last week
      - %52+ - since last week
      -
      -
      -
      -
      -
      - Customers -
      28441
      -
      -
      - +
      +
      +
      +
      + Customers +
      28441
      +
      +
      + +
      + 520 + newly registered
      - 520 - newly registered
      -
      -
      -
      -
      -
      - Comments -
      152 Unread
      -
      -
      - +
      +
      +
      +
      + Comments +
      152 Unread
      +
      +
      + +
      + 85 + responded
      - 85 - responded
      `; const block8 = ` -
      -
      -
      - hyper -
      Welcome Back
      - Don't have an account? - Create today! -
      +
      +
      + hyper +
      Welcome Back
      + Don't have an account? + Create today! +
      -
      - - +
      + + - - + + -
      -
      - setChecked(e.checked)} checked={checked} className="mr-2" /> - -
      - Forgot your password? +
      +
      + setChecked(e.checked)} checked={checked} /> +
      - -
      + +
      `; const block9 = ` -
      +
      Movie Information
      Morbi tristique blandit turpis. In viverra ligula id nulla hendrerit rutrum.
        -
      • +
      • Title
        Heat
      • -
      • +
      • Genre
        - - - + + +
      • -
      • +
      • Director
        Michael Mann
      • -
      • +
      • Actors
        Robert De Niro, Al Pacino
      • -
      • +
      • Plot
        A group of professional bank robbers start to feel the heat from police @@ -410,104 +412,104 @@ const Free = () => { `; const block10 = ` -
        +
        Card Title
        Vivamus id nisl interdum, blandit augue sit amet, eleifend mi.
        -
        +
        `; return ( <> - -
        + +
        - Create the screens + Create the screens your
        your visitors deserve to see

        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

        - +
        - hero-1 + hero-1
        - -
        -
        + +
        +
        One Product, Many Solutions
        -
        Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.
        +
        Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.
        - + -
        Built for Developers
        - Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. +
        Built for Developers
        + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
        - + -
        End-to-End Encryption
        - Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis. +
        End-to-End Encryption
        + Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis.
        - + -
        Easy to Use
        - Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper. +
        Easy to Use
        + Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper.
        - + -
        Fast & Global Support
        - Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus. +
        Fast & Global Support
        + Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus.
        - + -
        Open Source
        - Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat. +
        Open Source
        + Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat.
        - + -
        Trusted Securitty
        - Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend. +
        Trusted Securitty
        + Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend.
        - -
        + +
        Pricing Plans
        Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.
        -
        +
        Basic
        Plan description
        -
        +
        $9 per month
        -
        +
        • @@ -522,23 +524,23 @@ const Free = () => { Morbi tincidunt augue
        -
        -
        -
        +
        Premium
        Plan description
        -
        +
        $29 per month
        -
        +
        • @@ -557,23 +559,23 @@ const Free = () => { Duis ultricies lacus sed
        -
        -
        -
        +
        Enterprise
        Plan description
        -
        +
        $49 per month
        -
        +
        • @@ -600,8 +602,8 @@ const Free = () => { Nisi scelerisque
        -
        -
        @@ -609,37 +611,47 @@ const Free = () => {
        - -
        -
        -  POWERED BY DISCORD + +
        +
        +
        +  POWERED BY DISCORD +
        +
        Join Our Design Community
        +
        Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.
        +
        -
        Join Our Design Community
        -
        Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.
        -
        - +
        -
        🔥 Hot Deals!
        +
        + + 🔥 + {' '} + Hot Deals! +
        Libero voluptatum atque exercitationem praesentium provident odit.
        - + +
        - -
        + +
        • - Application +
        • @@ -674,144 +686,144 @@ const Free = () => {
        - -
        -
        -
        -
        -
        - Orders -
        152
        -
        -
        - + +
        +
        +
        +
        +
        +
        + Orders +
        152
        +
        +
        + +
        + 24 new + since last visit
        - 24 new - since last visit
        -
        -
        -
        -
        -
        - Revenue -
        $2.100
        -
        -
        - +
        +
        +
        +
        + Revenue +
        $2.100
        +
        +
        + +
        + %52+ + since last week
        - %52+ - since last week
        -
        -
        -
        -
        -
        - Customers -
        28441
        -
        -
        - +
        +
        +
        +
        + Customers +
        28441
        +
        +
        + +
        + 520 + newly registered
        - 520 - newly registered
        -
        -
        -
        -
        -
        - Comments -
        152 Unread
        -
        -
        - +
        +
        +
        +
        + Comments +
        152 Unread
        +
        +
        + +
        + 85 + responded
        - 85 - responded
        - -
        -
        -
        - hyper -
        Welcome Back
        - Do not have an account? - Create today! -
        + +
        +
        + hyper +
        Welcome Back
        + Don't have an account? + +
        -
        - - - - - - -
        -
        - setChecked(e.checked as boolean)} checked={checked} className="mr-2" /> - -
        - Forgot your password? +
        + + + + + + +
        +
        + setChecked(e.checked)} checked={checked} /> +
        - -
        + +
        - -
        + +
        Movie Information
        Morbi tristique blandit turpis. In viverra ligula id nulla hendrerit rutrum.
          -
        • +
        • Title
          Heat
        • -
        • +
        • Genre
          - - - + + +
        • -
        • +
        • Director
          Michael Mann
        • -
        • +
        • Actors
          Robert De Niro, Al Pacino
        • -
        • +
        • Plot
          A group of professional bank robbers start to feel the heat from police when they unknowingly leave a clue at their latest heist.
          @@ -822,15 +834,15 @@ const Free = () => {
          - -
          + +
          Card Title
          Vivamus id nisl interdum, blandit augue sit amet, eleifend mi.
          -
          +
          ); }; -export default Free; +export default BlocksDemo; diff --git a/pages/documentation/index.js b/pages/documentation/index.js new file mode 100644 index 00000000..0bb91266 --- /dev/null +++ b/pages/documentation/index.js @@ -0,0 +1,97 @@ +/* eslint-disable @next/next/no-sync-scripts */ +import React from 'react'; +import { CodeHighlight } from '../../demo/components/CodeHighlight'; +import styles from './index.module.css'; + +const Documentation = () => { + return ( + <> +
          +
          +
          +

          Current Version

          +

          React 17.x and PrimeReact 7.x

          + +
          Getting Started
          +

          + Sakai is an application template for React based on the popular NextJS framework. To get started, clone the repository from + GitHub and install the dependencies with npm or yarn. +

          + + {` +"npm install" or "yarn" +`} + + +

          + Next step is running the application using the start script and navigate to http://localhost:3000/ to view the application. That is it, you may now start with the development of your application using the Sakai + template. +

          + + + {` +"npm run dev" or "yarn dev" +`} + + +
          Dependencies
          +

          Dependencies of Sakai are listed below and needs to be defined at package.json.

          + + + {` +"primereact": "^8.6.0", //required: PrimeReact components +"primeicons": "^6.0.1", //required: Icons +"primeflex": "^3.2.1", //required: Utility CSS classes +"react-transition-group": "^4.4.1", //required: PrimeReact animations +`} + + +
          Structure
          +

          Sakai consists of a couple folders, demos and core has been separated so that you can easily remove what is not necessary for your application.

          +
            +
          • layout: Main layout files, needs to be present
          • +
          • demo: Contains demo related utilities and helpers
          • +
          • pages: Demo pages
          • +
          • public/demo: Assets used in demos
          • +
          • public/layout: Assets used in layout such as logo
          • +
          • styles/demo: CSS files only used in demos
          • +
          • styles/layout: SCSS files of the core layout
          • +
          + +
          Menu
          +

          Main menu is defined at AppMenu.js file based on MenuModel API.

          + +
          Integration with Existing NextJS Applications
          +

          Only the folders that are related to the layout needs to move in to your project. We've created a short tutorial with details.

          + +
          + +
          + +
          PrimeReact Theme
          +

          + Sakai theming is based on the PrimeReact theme being used. Default theme is lara-light-indigo. +

          + +
          SASS Variables
          +

          + In case you'd like to customize the main layout variables, open _variables.scss file under src/layout folder. Saving the changes will be reflected instantly at your browser. +

          + +
          src/layout/_variables.scss
          + + {` +/* General */ +$scale:14px; /* initial font size */ +$borderRadius:12px; /* border radius of layout element e.g. card, sidebar */ +$transitionDuration:.2s; /* transition duration of layout elements e.g. sidebar */ +`} + +
          +
          +
          + + ); +}; + +export default Documentation; diff --git a/app/(main)/documentation/index.module.css b/pages/documentation/index.module.css similarity index 100% rename from app/(main)/documentation/index.module.css rename to pages/documentation/index.module.css diff --git a/app/(main)/page.tsx b/pages/index.js similarity index 92% rename from app/(main)/page.tsx rename to pages/index.js index 2ce1d053..eb4630b5 100644 --- a/app/(main)/page.tsx +++ b/pages/index.js @@ -1,18 +1,14 @@ -/* eslint-disable @next/next/no-img-element */ -'use client'; +import getConfig from 'next/config'; import { Button } from 'primereact/button'; import { Chart } from 'primereact/chart'; import { Column } from 'primereact/column'; import { DataTable } from 'primereact/datatable'; import { Menu } from 'primereact/menu'; import React, { useContext, useEffect, useRef, useState } from 'react'; -import { ProductService } from '../../demo/service/ProductService'; -import { LayoutContext } from '../../layout/context/layoutcontext'; +import { ProductService } from '../demo/service/ProductService'; +import { LayoutContext } from '../layout/context/layoutcontext'; import Link from 'next/link'; -import { Demo } from '../../types/types'; -import { ChartData, ChartOptions } from 'chart.js'; - -const lineData: ChartData = { +const lineData = { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [ { @@ -35,14 +31,15 @@ const lineData: ChartData = { }; const Dashboard = () => { - const [products, setProducts] = useState([]); - const menu1 = useRef(null); - const menu2 = useRef(null); - const [lineOptions, setLineOptions] = useState({}); + const [products, setProducts] = useState(null); + const menu1 = useRef(null); + const menu2 = useRef(null); + const [lineOptions, setLineOptions] = useState(null); const { layoutConfig } = useContext(LayoutContext); + const contextPath = getConfig().publicRuntimeConfig.contextPath; const applyLightTheme = () => { - const lineOptions: ChartOptions = { + const lineOptions = { plugins: { legend: { labels: { @@ -106,7 +103,8 @@ const Dashboard = () => { }; useEffect(() => { - ProductService.getProductsSmall().then((data) => setProducts(data)); + const productService = new ProductService(); + productService.getProductsSmall().then((data) => setProducts(data)); }, []); useEffect(() => { @@ -117,11 +115,8 @@ const Dashboard = () => { } }, [layoutConfig.colorScheme]); - const formatCurrency = (value: number) => { - return value?.toLocaleString('en-US', { - style: 'currency', - currency: 'USD' - }); + const formatCurrency = (value) => { + return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); }; return ( @@ -191,7 +186,7 @@ const Dashboard = () => {
          Recent Sales
          - {data.image}} /> + {data.image}} /> formatCurrency(data.price)} /> { style={{ width: '15%' }} body={() => ( <> -
          TAKE THE NEXT STEP
          Try PrimeBlocks
          - - Get Started + + + Get Started +
          diff --git a/app/(full-page)/landing/page.tsx b/pages/landing/index.js similarity index 70% rename from app/(full-page)/landing/page.tsx rename to pages/landing/index.js index b3bfe699..fc45e80d 100644 --- a/app/(full-page)/landing/page.tsx +++ b/pages/landing/index.js @@ -1,66 +1,61 @@ -'use client'; -/* eslint-disable @next/next/no-img-element */ -import React, { useContext, useRef, useState } from 'react'; +import React, { useContext, useRef } from 'react'; import Link from 'next/link'; - +import getConfig from 'next/config'; import { StyleClass } from 'primereact/styleclass'; import { Button } from 'primereact/button'; import { Ripple } from 'primereact/ripple'; import { Divider } from 'primereact/divider'; -import { LayoutContext } from '../../../layout/context/layoutcontext'; -import { NodeRef } from '../../../types/types'; -import { classNames } from 'primereact/utils'; +import AppConfig from '../../layout/AppConfig'; +import { LayoutContext } from '../../layout/context/layoutcontext'; const LandingPage = () => { - const [isHidden, setIsHidden] = useState(false); + const contextPath = getConfig().publicRuntimeConfig.contextPath; const { layoutConfig } = useContext(LayoutContext); - const menuRef = useRef(null); - - const toggleMenuItemClick = () => { - setIsHidden((prevState) => !prevState); - }; + const menuRef = useRef(); return (
          - - Sakai Logo - SAKAI + + + Sakai Logo + SAKAI + - + - @@ -68,20 +63,16 @@ const LandingPage = () => {
          + style={{ background: 'linear-gradient(0deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2)), radial-gradient(77.36% 256.97% at 77.36% 57.52%, #EEEFAF 0%, #C3E3FA 100%)', clipPath: 'ellipse(150% 87% at 93% 13%)' }}>

          Eu sem integereget magna fermentum

          Sed blandit libero volutpat sed cras. Fames ac turpis egestas integer. Placerat in egestas erat...

          - +
          - Hero Image + Hero Image
          @@ -99,17 +90,9 @@ const LandingPage = () => { padding: '2px', borderRadius: '10px', background: 'linear-gradient(90deg, rgba(253, 228, 165, 0.2), rgba(187, 199, 205, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(187, 199, 205, 0.2))' - }} - > + }}>
          -
          +
          Easy to Use
          @@ -125,17 +108,9 @@ const LandingPage = () => { padding: '2px', borderRadius: '10px', background: 'linear-gradient(90deg, rgba(145,226,237,0.2),rgba(251, 199, 145, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(172, 180, 223, 0.2))' - }} - > + }}>
          -
          +
          Fresh Design
          @@ -151,17 +126,9 @@ const LandingPage = () => { padding: '2px', borderRadius: '10px', background: 'linear-gradient(90deg, rgba(145, 226, 237, 0.2), rgba(172, 180, 223, 0.2)), linear-gradient(180deg, rgba(172, 180, 223, 0.2), rgba(246, 158, 188, 0.2))' - }} - > + }}>
          -
          +
          Well Documented
          @@ -177,17 +144,9 @@ const LandingPage = () => { padding: '2px', borderRadius: '10px', background: 'linear-gradient(90deg, rgba(187, 199, 205, 0.2),rgba(251, 199, 145, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2),rgba(145, 210, 204, 0.2))' - }} - > + }}>
          -
          +
          Responsive Layout
          @@ -203,17 +162,9 @@ const LandingPage = () => { padding: '2px', borderRadius: '10px', background: 'linear-gradient(90deg, rgba(187, 199, 205, 0.2),rgba(246, 158, 188, 0.2)), linear-gradient(180deg, rgba(145, 226, 237, 0.2),rgba(160, 210, 250, 0.2))' - }} - > + }}>
          -
          +
          Clean Code
          @@ -229,17 +180,9 @@ const LandingPage = () => { padding: '2px', borderRadius: '10px', background: 'linear-gradient(90deg, rgba(251, 199, 145, 0.2), rgba(246, 158, 188, 0.2)), linear-gradient(180deg, rgba(172, 180, 223, 0.2), rgba(212, 162, 221, 0.2))' - }} - > + }}>
          -
          +
          Dark Mode
          @@ -255,17 +198,9 @@ const LandingPage = () => { padding: '2px', borderRadius: '10px', background: 'linear-gradient(90deg, rgba(145, 210, 204, 0.2), rgba(160, 210, 250, 0.2)), linear-gradient(180deg, rgba(187, 199, 205, 0.2), rgba(145, 210, 204, 0.2))' - }} - > + }}>
          -
          +
          Ready to Use
          @@ -281,17 +216,9 @@ const LandingPage = () => { padding: '2px', borderRadius: '10px', background: 'linear-gradient(90deg, rgba(145, 210, 204, 0.2), rgba(212, 162, 221, 0.2)), linear-gradient(180deg, rgba(251, 199, 145, 0.2), rgba(160, 210, 250, 0.2))' - }} - > + }}>
          -
          +
          Modern Practices
          @@ -307,17 +234,9 @@ const LandingPage = () => { padding: '2px', borderRadius: '10px', background: 'linear-gradient(90deg, rgba(160, 210, 250, 0.2), rgba(212, 162, 221, 0.2)), linear-gradient(180deg, rgba(246, 158, 188, 0.2), rgba(212, 162, 221, 0.2))' - }} - > + }}>
          -
          +
          Privacy
          @@ -328,11 +247,7 @@ const LandingPage = () => {
          + style={{ borderRadius: '20px', background: 'linear-gradient(0deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.6)), radial-gradient(77.36% 256.97% at 77.36% 57.52%, #EFE1AF 0%, #C3DCFA 100%)' }}>

          Joséphine Miller

          Peak Interactive @@ -340,7 +255,7 @@ const LandingPage = () => { “Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.”

          - Company logo + Company logo
          @@ -354,18 +269,11 @@ const LandingPage = () => {
          - mockup mobile + mockup mobile
          -
          +

          Congue Quisque Egestas

          @@ -377,14 +285,7 @@ const LandingPage = () => {
          -
          +

          Celerisque Eu Ultrices

          @@ -394,7 +295,7 @@ const LandingPage = () => {
          - mockup + mockup
          @@ -409,11 +310,11 @@ const LandingPage = () => {

          Free

          - free + free
          $0 per month - +
            @@ -440,11 +341,11 @@ const LandingPage = () => {

            Startup

            - startup + startup
            $1 per month - +
              @@ -471,11 +372,11 @@ const LandingPage = () => {

              Enterprise

              - enterprise + enterprise
              $999 per month - +
                @@ -504,9 +405,11 @@ const LandingPage = () => {
                - - footer sections - SAKAI + + + footer sections + SAKAI +
                @@ -533,7 +436,7 @@ const LandingPage = () => { Discord Events - badge + FAQ Blog @@ -554,4 +457,13 @@ const LandingPage = () => { ); }; +LandingPage.getLayout = function getLayout(page) { + return ( + + {page} + + + ); +}; + export default LandingPage; diff --git a/app/(main)/pages/crud/page.tsx b/pages/pages/crud/index.js similarity index 70% rename from app/(main)/pages/crud/page.tsx rename to pages/pages/crud/index.js index 315e5ab7..421b8162 100644 --- a/app/(main)/pages/crud/page.tsx +++ b/pages/pages/crud/index.js @@ -1,30 +1,27 @@ -/* eslint-disable @next/next/no-img-element */ -'use client'; +import getConfig from 'next/config'; import { Button } from 'primereact/button'; import { Column } from 'primereact/column'; import { DataTable } from 'primereact/datatable'; import { Dialog } from 'primereact/dialog'; import { FileUpload } from 'primereact/fileupload'; -import { InputNumber, InputNumberValueChangeEvent } from 'primereact/inputnumber'; +import { InputNumber } from 'primereact/inputnumber'; import { InputText } from 'primereact/inputtext'; import { InputTextarea } from 'primereact/inputtextarea'; -import { RadioButton, RadioButtonChangeEvent } from 'primereact/radiobutton'; +import { RadioButton } from 'primereact/radiobutton'; import { Rating } from 'primereact/rating'; import { Toast } from 'primereact/toast'; import { Toolbar } from 'primereact/toolbar'; import { classNames } from 'primereact/utils'; import React, { useEffect, useRef, useState } from 'react'; -import { ProductService } from '../../../../demo/service/ProductService'; -import { Demo } from '../../../../types/types'; +import { ProductService } from '../../../demo/service/ProductService'; -/* @todo Used 'as any' for types here. Will fix in next version due to onSelectionChange event type issue. */ const Crud = () => { - let emptyProduct: Demo.Product = { - id: '', + let emptyProduct = { + id: null, name: '', - image: '', + image: null, description: '', - category: '', + category: null, price: 0, quantity: 0, rating: 0, @@ -35,22 +32,21 @@ const Crud = () => { const [productDialog, setProductDialog] = useState(false); const [deleteProductDialog, setDeleteProductDialog] = useState(false); const [deleteProductsDialog, setDeleteProductsDialog] = useState(false); - const [product, setProduct] = useState(emptyProduct); + const [product, setProduct] = useState(emptyProduct); const [selectedProducts, setSelectedProducts] = useState(null); const [submitted, setSubmitted] = useState(false); - const [globalFilter, setGlobalFilter] = useState(''); - const toast = useRef(null); - const dt = useRef>(null); + const [globalFilter, setGlobalFilter] = useState(null); + const toast = useRef(null); + const dt = useRef(null); + const contextPath = getConfig().publicRuntimeConfig.contextPath; useEffect(() => { - ProductService.getProducts().then((data) => setProducts(data as any)); + const productService = new ProductService(); + productService.getProducts().then((data) => setProducts(data)); }, []); - const formatCurrency = (value: number) => { - return value.toLocaleString('en-US', { - style: 'currency', - currency: 'USD' - }); + const formatCurrency = (value) => { + return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); }; const openNew = () => { @@ -76,63 +72,49 @@ const Crud = () => { setSubmitted(true); if (product.name.trim()) { - let _products = [...(products as any)]; + let _products = [...products]; let _product = { ...product }; if (product.id) { const index = findIndexById(product.id); _products[index] = _product; - toast.current?.show({ - severity: 'success', - summary: 'Successful', - detail: 'Product Updated', - life: 3000 - }); + toast.current.show({ severity: 'success', summary: 'Successful', detail: 'Product Updated', life: 3000 }); } else { _product.id = createId(); + _product.code = createId(); _product.image = 'product-placeholder.svg'; _products.push(_product); - toast.current?.show({ - severity: 'success', - summary: 'Successful', - detail: 'Product Created', - life: 3000 - }); + toast.current.show({ severity: 'success', summary: 'Successful', detail: 'Product Created', life: 3000 }); } - setProducts(_products as any); + setProducts(_products); setProductDialog(false); setProduct(emptyProduct); } }; - const editProduct = (product: Demo.Product) => { + const editProduct = (product) => { setProduct({ ...product }); setProductDialog(true); }; - const confirmDeleteProduct = (product: Demo.Product) => { + const confirmDeleteProduct = (product) => { setProduct(product); setDeleteProductDialog(true); }; const deleteProduct = () => { - let _products = (products as any)?.filter((val: any) => val.id !== product.id); + let _products = products.filter((val) => val.id !== product.id); setProducts(_products); setDeleteProductDialog(false); setProduct(emptyProduct); - toast.current?.show({ - severity: 'success', - summary: 'Successful', - detail: 'Product Deleted', - life: 3000 - }); + toast.current.show({ severity: 'success', summary: 'Successful', detail: 'Product Deleted', life: 3000 }); }; - const findIndexById = (id: string) => { + const findIndexById = (id) => { let index = -1; - for (let i = 0; i < (products as any)?.length; i++) { - if ((products as any)[i].id === id) { + for (let i = 0; i < products.length; i++) { + if (products[i].id === id) { index = i; break; } @@ -151,7 +133,7 @@ const Crud = () => { }; const exportCSV = () => { - dt.current?.exportCSV(); + dt.current.exportCSV(); }; const confirmDeleteSelected = () => { @@ -159,25 +141,20 @@ const Crud = () => { }; const deleteSelectedProducts = () => { - let _products = (products as any)?.filter((val: any) => !(selectedProducts as any)?.includes(val)); + let _products = products.filter((val) => !selectedProducts.includes(val)); setProducts(_products); setDeleteProductsDialog(false); setSelectedProducts(null); - toast.current?.show({ - severity: 'success', - summary: 'Successful', - detail: 'Products Deleted', - life: 3000 - }); + toast.current.show({ severity: 'success', summary: 'Successful', detail: 'Products Deleted', life: 3000 }); }; - const onCategoryChange = (e: RadioButtonChangeEvent) => { + const onCategoryChange = (e) => { let _product = { ...product }; _product['category'] = e.value; setProduct(_product); }; - const onInputChange = (e: React.ChangeEvent, name: string) => { + const onInputChange = (e, name) => { const val = (e.target && e.target.value) || ''; let _product = { ...product }; _product[`${name}`] = val; @@ -185,7 +162,7 @@ const Crud = () => { setProduct(_product); }; - const onInputNumberChange = (e: InputNumberValueChangeEvent, name: string) => { + const onInputNumberChange = (e, name) => { const val = e.value || 0; let _product = { ...product }; _product[`${name}`] = val; @@ -197,8 +174,8 @@ const Crud = () => { return (
                -
                ); @@ -207,13 +184,13 @@ const Crud = () => { const rightToolbarTemplate = () => { return ( - -
                ); const productDialogFooter = ( <> -
                diff --git a/app/(main)/pages/empty/page.tsx b/pages/pages/empty/index.js similarity index 93% rename from app/(main)/pages/empty/page.tsx rename to pages/pages/empty/index.js index 6b4c5676..390cb1fc 100644 --- a/app/(main)/pages/empty/page.tsx +++ b/pages/pages/empty/index.js @@ -1,4 +1,5 @@ import React from 'react'; +import Link from 'next/link'; const EmptyPage = () => { return ( diff --git a/pages/pages/notfound/index.js b/pages/pages/notfound/index.js new file mode 100644 index 00000000..09b93a10 --- /dev/null +++ b/pages/pages/notfound/index.js @@ -0,0 +1,70 @@ +import getConfig from 'next/config'; +import { useRouter } from 'next/router'; +import React from 'react'; +import AppConfig from '../../../layout/AppConfig'; +import { Button } from 'primereact/button'; +import Link from 'next/link'; + +const NotFoundPage = () => { + const contextPath = getConfig().publicRuntimeConfig.contextPath; + const router = useRouter(); + + return ( + + ); +}; + +NotFoundPage.getLayout = function getLayout(page) { + return ( + + {page} + + + ); +}; + +export default NotFoundPage; diff --git a/app/(main)/pages/timeline/page.tsx b/pages/pages/timeline/index.js similarity index 75% rename from app/(main)/pages/timeline/page.tsx rename to pages/pages/timeline/index.js index 736c3005..a6e705c3 100644 --- a/app/(main)/pages/timeline/page.tsx +++ b/pages/pages/timeline/index.js @@ -1,15 +1,12 @@ -/* eslint-disable @next/next/no-img-element */ -'use client'; - -import React from 'react'; - +import getConfig from 'next/config'; import { Button } from 'primereact/button'; import { Card } from 'primereact/card'; import { Timeline } from 'primereact/timeline'; -import { CustomEvent } from '../../../../types/types'; +import { classNames } from 'primereact/utils'; +import React from 'react'; const TimelineDemo = () => { - const customEvents: CustomEvent[] = [ + const customEvents = [ { status: 'Ordered', date: '15/10/2025 10:30', @@ -17,42 +14,30 @@ const TimelineDemo = () => { color: '#9C27B0', image: 'game-controller.jpg' }, - { - status: 'Processing', - date: '15/10/2025 14:00', - icon: 'pi pi-cog', - color: '#673AB7' - }, - { - status: 'Shipped', - date: '15/10/2025 16:15', - icon: 'pi pi-envelope', - color: '#FF9800' - }, - { - status: 'Delivered', - date: '16/10/2025 10:00', - icon: 'pi pi-check', - color: '#607D8B' - } + { status: 'Processing', date: '15/10/2025 14:00', icon: 'pi pi-cog', color: '#673AB7' }, + { status: 'Shipped', date: '15/10/2025 16:15', icon: 'pi pi-envelope', color: '#FF9800' }, + { status: 'Delivered', date: '16/10/2025 10:00', icon: 'pi pi-check', color: '#607D8B' } ]; const horizontalEvents = ['2023', '2024', '2025', '2026']; + const contextPath = getConfig().publicRuntimeConfig.contextPath; - const customizedContent = (item: CustomEvent) => { + const customizedContent = (item) => { return ( - {item.image && (e.currentTarget.src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png')} alt={item.name} width={200} className="shadow-2 mb-3" />} + {item.image && ( + (e.target.src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png')} alt={item.name} width={200} className="shadow-2 mb-3" /> + )}

                Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!

                - +
                ); }; - const customizedMarker = (item: CustomEvent) => { + const customizedMarker = (item) => { return ( @@ -99,10 +84,10 @@ const TimelineDemo = () => {
                Horizontal
                Top Align
                - item} /> + item} />
                Bottom Align
                - item} /> + item} />
                Alternate Align
                item} opposite={ } /> diff --git a/app/(main)/uikit/button/page.tsx b/pages/uikit/button/index.js similarity index 50% rename from app/(main)/uikit/button/page.tsx rename to pages/uikit/button/index.js index 69196ed2..dc528806 100644 --- a/app/(main)/uikit/button/page.tsx +++ b/pages/uikit/button/index.js @@ -1,9 +1,7 @@ -'use client'; import React, { useState } from 'react'; -import { SplitButton } from 'primereact/splitbutton'; import { Button } from 'primereact/button'; +import { SplitButton } from 'primereact/splitbutton'; import styles from './index.module.scss'; -import { classNames } from 'primereact/utils'; const ButtonDemo = () => { const [loading1, setLoading1] = useState(false); @@ -66,7 +64,7 @@ const ButtonDemo = () => {
                - +
                @@ -74,39 +72,39 @@ const ButtonDemo = () => {
                Severities
              Text
              -
              Outlined
              -
              @@ -122,31 +120,31 @@ const ButtonDemo = () => {
              SplitButton
              - - - - - + + + + +
              Template
              - - -
              Rounded
              -
              Rounded Icons
              -
              Rounded Text
              -
              Rounded Outlined
              -
              diff --git a/app/(main)/uikit/button/index.module.scss b/pages/uikit/button/index.module.scss similarity index 98% rename from app/(main)/uikit/button/index.module.scss rename to pages/uikit/button/index.module.scss index 2ee14829..d0cc344e 100644 --- a/app/(main)/uikit/button/index.module.scss +++ b/pages/uikit/button/index.module.scss @@ -1,6 +1,4 @@ -.p-button{ - padding: 0%; -&.google { +.google { background: linear-gradient(to left, var(--purple-600) 50%, var(--purple-700) 50%); background-size: 200% 100%; background-position: right bottom; @@ -10,7 +8,6 @@ align-items: stretch; padding: 0; - &:enabled:hover { background: linear-gradient(to left, var(--purple-600) 50%, var(--purple-700) 50%); background-size: 200% 100%; @@ -23,7 +20,7 @@ } } -&.twitter { +.twitter { background: linear-gradient(to left, var(--blue-400) 50%, var(--blue-500) 50%); background-size: 200% 100%; background-position: right bottom; @@ -45,7 +42,7 @@ } } -&.discord { +.discord { background: linear-gradient(to left, var(--bluegray-700) 50%, var(--bluegray-800) 50%); background-size: 200% 100%; background-position: right bottom; @@ -147,5 +144,4 @@ -button .p-buttonset .p-button { margin-bottom: 0; } -} } \ No newline at end of file diff --git a/app/(main)/uikit/charts/page.tsx b/pages/uikit/charts/index.js similarity index 73% rename from app/(main)/uikit/charts/page.tsx rename to pages/uikit/charts/index.js index dbf71fe0..cd78f294 100644 --- a/app/(main)/uikit/charts/page.tsx +++ b/pages/uikit/charts/index.js @@ -1,43 +1,40 @@ -'use client'; -import { ChartData, ChartOptions } from 'chart.js'; import { Chart } from 'primereact/chart'; import React, { useContext, useEffect, useState } from 'react'; -import { LayoutContext } from '../../../../layout/context/layoutcontext'; -import type { ChartDataState, ChartOptionsState } from '../../../../types/types'; +import { LayoutContext } from '../../../layout/context/layoutcontext'; const ChartDemo = () => { - const [options, setOptions] = useState({}); - const [data, setChartData] = useState({}); + const [options, setOptions] = useState({}); + const [data, setChartData] = useState({}); const { layoutConfig } = useContext(LayoutContext); useEffect(() => { const documentStyle = getComputedStyle(document.documentElement); - const textColor = documentStyle.getPropertyValue('--text-color') || '#495057'; - const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary') || '#6c757d'; - const surfaceBorder = documentStyle.getPropertyValue('--surface-border') || '#dfe7ef'; - const barData: ChartData = { + const textColor = documentStyle.getPropertyValue('--text-color'); + const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary'); + const surfaceBorder = documentStyle.getPropertyValue('--surface-border'); + const barData = { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [ { label: 'My First dataset', - backgroundColor: documentStyle.getPropertyValue('--primary-500') || '#6366f1', - borderColor: documentStyle.getPropertyValue('--primary-500') || '#6366f1', + backgroundColor: documentStyle.getPropertyValue('--primary-500'), + borderColor: documentStyle.getPropertyValue('--primary-500'), data: [65, 59, 80, 81, 56, 55, 40] }, { label: 'My Second dataset', - backgroundColor: documentStyle.getPropertyValue('--primary-200') || '#bcbdf9', - borderColor: documentStyle.getPropertyValue('--primary-200') || '#bcbdf9', + backgroundColor: documentStyle.getPropertyValue('--primary-200'), + borderColor: documentStyle.getPropertyValue('--primary-200'), data: [28, 48, 40, 19, 86, 27, 90] } ] }; - const barOptions: ChartOptions = { + const barOptions = { plugins: { legend: { labels: { - color: textColor + fontColor: textColor } } }, @@ -46,14 +43,12 @@ const ChartDemo = () => { ticks: { color: textColorSecondary, font: { - weight: '500' + weight: 500 } }, grid: { - display: false - }, - border: { - display: false + display: false, + drawBorder: false } }, y: { @@ -61,27 +56,25 @@ const ChartDemo = () => { color: textColorSecondary }, grid: { - color: surfaceBorder - }, - border: { - display: false + color: surfaceBorder, + drawBorder: false } } } }; - const pieData: ChartData = { + const pieData = { labels: ['A', 'B', 'C'], datasets: [ { data: [540, 325, 702], - backgroundColor: [documentStyle.getPropertyValue('--indigo-500') || '#6366f1', documentStyle.getPropertyValue('--purple-500') || '#a855f7', documentStyle.getPropertyValue('--teal-500') || '#14b8a6'], - hoverBackgroundColor: [documentStyle.getPropertyValue('--indigo-400') || '#8183f4', documentStyle.getPropertyValue('--purple-400') || '#b975f9', documentStyle.getPropertyValue('--teal-400') || '#41c5b7'] + backgroundColor: [documentStyle.getPropertyValue('--indigo-500'), documentStyle.getPropertyValue('--purple-500'), documentStyle.getPropertyValue('--teal-500')], + hoverBackgroundColor: [documentStyle.getPropertyValue('--indigo-400'), documentStyle.getPropertyValue('--purple-400'), documentStyle.getPropertyValue('--teal-400')] } ] }; - const pieOptions: ChartOptions = { + const pieOptions = { plugins: { legend: { labels: { @@ -92,33 +85,33 @@ const ChartDemo = () => { } }; - const lineData: ChartData = { + const lineData = { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [ { label: 'First Dataset', data: [65, 59, 80, 81, 56, 55, 40], fill: false, - backgroundColor: documentStyle.getPropertyValue('--primary-500') || '#6366f1', - borderColor: documentStyle.getPropertyValue('--primary-500') || '#6366f1', + backgroundColor: documentStyle.getPropertyValue('--primary-500'), + borderColor: documentStyle.getPropertyValue('--primary-500'), tension: 0.4 }, { label: 'Second Dataset', data: [28, 48, 40, 19, 86, 27, 90], fill: false, - backgroundColor: documentStyle.getPropertyValue('--primary-200') || '#bcbdf9', - borderColor: documentStyle.getPropertyValue('--primary-200') || '#bcbdf9', + backgroundColor: documentStyle.getPropertyValue('--primary-200'), + borderColor: documentStyle.getPropertyValue('--primary-200'), tension: 0.4 } ] }; - const lineOptions: ChartOptions = { + const lineOptions = { plugins: { legend: { labels: { - color: textColor + fontColor: textColor } } }, @@ -128,10 +121,8 @@ const ChartDemo = () => { color: textColorSecondary }, grid: { - color: surfaceBorder - }, - border: { - display: false + color: surfaceBorder, + drawBorder: false } }, y: { @@ -139,32 +130,25 @@ const ChartDemo = () => { color: textColorSecondary }, grid: { - color: surfaceBorder - }, - border: { - display: false + color: surfaceBorder, + drawBorder: false } } } }; - const polarData: ChartData = { + const polarData = { datasets: [ { data: [11, 16, 7, 3], - backgroundColor: [ - documentStyle.getPropertyValue('--indigo-500') || '#6366f1', - documentStyle.getPropertyValue('--purple-500') || '#a855f7', - documentStyle.getPropertyValue('--teal-500') || '#14b8a6', - documentStyle.getPropertyValue('--orange-500') || '#f97316' - ], + backgroundColor: [documentStyle.getPropertyValue('--indigo-500'), documentStyle.getPropertyValue('--purple-500'), documentStyle.getPropertyValue('--teal-500'), documentStyle.getPropertyValue('--orange-500')], label: 'My dataset' } ], labels: ['Indigo', 'Purple', 'Teal', 'Orange'] }; - const polarOptions: ChartOptions = { + const polarOptions = { plugins: { legend: { labels: { @@ -181,35 +165,35 @@ const ChartDemo = () => { } }; - const radarData: ChartData = { + const radarData = { labels: ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'], datasets: [ { label: 'My First dataset', - borderColor: documentStyle.getPropertyValue('--indigo-400') || '#8183f4', - pointBackgroundColor: documentStyle.getPropertyValue('--indigo-400') || '#8183f4', - pointBorderColor: documentStyle.getPropertyValue('--indigo-400') || '#8183f4', + borderColor: documentStyle.getPropertyValue('--indigo-400'), + pointBackgroundColor: documentStyle.getPropertyValue('--indigo-400'), + pointBorderColor: documentStyle.getPropertyValue('--indigo-400'), pointHoverBackgroundColor: textColor, - pointHoverBorderColor: documentStyle.getPropertyValue('--indigo-400') || '#8183f4', + pointHoverBorderColor: documentStyle.getPropertyValue('--indigo-400'), data: [65, 59, 90, 81, 56, 55, 40] }, { label: 'My Second dataset', - borderColor: documentStyle.getPropertyValue('--purple-400') || '#b975f9', - pointBackgroundColor: documentStyle.getPropertyValue('--purple-400') || '#b975f9', - pointBorderColor: documentStyle.getPropertyValue('--purple-400') || '#b975f9', + borderColor: documentStyle.getPropertyValue('--purple-400'), + pointBackgroundColor: documentStyle.getPropertyValue('--purple-400'), + pointBorderColor: documentStyle.getPropertyValue('--purple-400'), pointHoverBackgroundColor: textColor, - pointHoverBorderColor: documentStyle.getPropertyValue('--purple-400') || '#b975f9', + pointHoverBorderColor: documentStyle.getPropertyValue('--purple-400'), data: [28, 48, 40, 19, 96, 27, 100] } ] }; - const radarOptions: ChartOptions = { + const radarOptions = { plugins: { legend: { labels: { - color: textColor + fontColor: textColor } } }, diff --git a/pages/uikit/file/index.js b/pages/uikit/file/index.js new file mode 100644 index 00000000..3638dacb --- /dev/null +++ b/pages/uikit/file/index.js @@ -0,0 +1,26 @@ +import React, { useRef } from 'react'; +import { FileUpload } from 'primereact/fileupload'; + +const FileDemo = () => { + const toast = useRef(null); + + const onUpload = () => { + toast.current.show({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 }); + }; + + return ( +
              +
              +
              +
              Advanced
              + + +
              Basic
              + +
              +
              +
              + ); +}; + +export default FileDemo; diff --git a/app/(main)/uikit/floatlabel/page.tsx b/pages/uikit/floatlabel/index.js similarity index 83% rename from app/(main)/uikit/floatlabel/page.tsx rename to pages/uikit/floatlabel/index.js index e602f410..df535e1a 100644 --- a/app/(main)/uikit/floatlabel/page.tsx +++ b/pages/uikit/floatlabel/index.js @@ -1,28 +1,26 @@ -'use client'; import React, { useState, useEffect } from 'react'; import { InputText } from 'primereact/inputtext'; import { InputTextarea } from 'primereact/inputtextarea'; import { InputMask } from 'primereact/inputmask'; import { InputNumber } from 'primereact/inputnumber'; -import { AutoComplete, AutoCompleteCompleteEvent } from 'primereact/autocomplete'; +import { AutoComplete } from 'primereact/autocomplete'; import { Calendar } from 'primereact/calendar'; import { Chips } from 'primereact/chips'; import { Dropdown } from 'primereact/dropdown'; import { MultiSelect } from 'primereact/multiselect'; -import { CountryService } from '../../../../demo/service/CountryService'; -import type { Demo } from '../../../../types/types'; +import { CountryService } from '../../../demo/service/CountryService'; const FloatLabelDemo = () => { - const [countries, setCountries] = useState([]); - const [filteredCountries, setFilteredCountries] = useState([]); + const [countries, setCountries] = useState([]); + const [filteredCountries, setFilteredCountries] = useState(null); const [value1, setValue1] = useState(''); const [value2, setValue2] = useState(null); const [value3, setValue3] = useState(''); const [value4, setValue4] = useState(''); - const [value5, setValue5] = useState(null); - const [value6, setValue6] = useState([]); + const [value5, setValue5] = useState(''); + const [value6, setValue6] = useState([]); const [value7, setValue7] = useState(''); - const [value8, setValue8] = useState(null); + const [value8, setValue8] = useState(null); const [value9, setValue9] = useState(''); const [value10, setValue10] = useState(null); const [value11, setValue11] = useState(null); @@ -37,12 +35,15 @@ const FloatLabelDemo = () => { ]; useEffect(() => { - CountryService.getCountries().then((countries) => { + const countryService = new CountryService(); + countryService.getCountries().then((countries) => { setCountries(countries); }); }, []); - const searchCountry = (event: AutoCompleteCompleteEvent) => { + const searchCountry = (event) => { + // in a real application, make a request to a remote url with the query and + // return filtered results, for demo we filter at client side const filtered = []; const query = event.query; for (let i = 0; i < countries.length; i++) { @@ -57,9 +58,6 @@ const FloatLabelDemo = () => { return (
              Float Label
              -

              - All input text components support floating labels by adding (.p-float-label) to wrapper class. -

              @@ -89,25 +87,25 @@ const FloatLabelDemo = () => {
              - setValue5(e.value ?? '')}> + setValue5(e.value)}>
              - setValue6(e.value ?? [])}> + setValue6(e.value)}>
              - setValue7(e.value ?? '')}> + setValue7(e.value)}>
              - setValue8(e.target.value ?? null)}> + setValue8(e.target.value)}>
              @@ -136,7 +134,7 @@ const FloatLabelDemo = () => {
              - setValue12(e.target.value)}> + setValue12(e.target.value)} autoResize>
              diff --git a/app/(main)/uikit/formlayout/page.tsx b/pages/uikit/formlayout/index.js similarity index 89% rename from app/(main)/uikit/formlayout/page.tsx rename to pages/uikit/formlayout/index.js index 01e98052..0df817b9 100644 --- a/app/(main)/uikit/formlayout/page.tsx +++ b/pages/uikit/formlayout/index.js @@ -1,30 +1,16 @@ -'use client'; - -import React, { useState, useEffect, useMemo } from 'react'; +import React, { useState } from 'react'; import { InputText } from 'primereact/inputtext'; import { Button } from 'primereact/button'; import { InputTextarea } from 'primereact/inputtextarea'; import { Dropdown } from 'primereact/dropdown'; -interface DropdownItem { - name: string; - code: string; -} - const FormLayoutDemo = () => { - const [dropdownItem, setDropdownItem] = useState(null); - const dropdownItems: DropdownItem[] = useMemo( - () => [ - { name: 'Option 1', code: 'Option 1' }, - { name: 'Option 2', code: 'Option 2' }, - { name: 'Option 3', code: 'Option 3' } - ], - [] - ); - - useEffect(() => { - setDropdownItem(dropdownItems[0]); - }, [dropdownItems]); + const [dropdownItem, setDropdownItem] = useState(null); + const dropdownItems = [ + { name: 'Option 1', code: 'Option 1' }, + { name: 'Option 2', code: 'Option 2' }, + { name: 'Option 3', code: 'Option 3' } + ]; return (
              @@ -124,7 +110,7 @@ const FormLayoutDemo = () => {
              - +
              diff --git a/app/(main)/uikit/input/page.tsx b/pages/uikit/input/index.js similarity index 81% rename from app/(main)/uikit/input/page.tsx rename to pages/uikit/input/index.js index b6319af7..c7b35d62 100644 --- a/app/(main)/uikit/input/page.tsx +++ b/pages/uikit/input/index.js @@ -1,46 +1,41 @@ -'use client'; -import { AutoComplete, AutoCompleteCompleteEvent } from 'primereact/autocomplete'; -import { Button } from 'primereact/button'; -import { Calendar } from 'primereact/calendar'; -import { Checkbox, CheckboxChangeEvent } from 'primereact/checkbox'; -import { Chips } from 'primereact/chips'; -import { ColorPicker, ColorPickerHSBType, ColorPickerRGBType } from 'primereact/colorpicker'; -import { Dropdown } from 'primereact/dropdown'; -import { InputNumber } from 'primereact/inputnumber'; -import { InputSwitch } from 'primereact/inputswitch'; +import React, { useEffect, useState } from 'react'; import { InputText } from 'primereact/inputtext'; import { InputTextarea } from 'primereact/inputtextarea'; +import { AutoComplete } from 'primereact/autocomplete'; +import { Calendar } from 'primereact/calendar'; +import { Chips } from 'primereact/chips'; +import { Slider } from 'primereact/slider'; import { Knob } from 'primereact/knob'; +import { Rating } from 'primereact/rating'; +import { ColorPicker } from 'primereact/colorpicker'; +import { RadioButton } from 'primereact/radiobutton'; +import { Checkbox } from 'primereact/checkbox'; +import { InputSwitch } from 'primereact/inputswitch'; import { ListBox } from 'primereact/listbox'; +import { Dropdown } from 'primereact/dropdown'; +import { ToggleButton } from 'primereact/togglebutton'; import { MultiSelect } from 'primereact/multiselect'; -import { RadioButton } from 'primereact/radiobutton'; -import { Rating } from 'primereact/rating'; +import { TreeSelect } from 'primereact/treeselect'; import { SelectButton } from 'primereact/selectbutton'; -import { Slider } from 'primereact/slider'; -import { ToggleButton } from 'primereact/togglebutton'; -import React, { useEffect, useState } from 'react'; -import { CountryService } from '../../../../demo/service/CountryService'; -import type { Demo, Page } from '../../../../types/types'; - -interface InputValue { - name: string; - code: string; -} +import { Button } from 'primereact/button'; +import { InputNumber } from 'primereact/inputnumber'; +import { CountryService } from '../../../demo/service/CountryService'; +import { NodeService } from '../../../demo/service/NodeService'; -const InputDemo: Page = () => { +export const InputDemo = () => { const [floatValue, setFloatValue] = useState(''); - const [autoValue, setAutoValue] = useState([]); + const [autoValue, setAutoValue] = useState(null); const [selectedAutoValue, setSelectedAutoValue] = useState(null); - const [autoFilteredValue, setAutoFilteredValue] = useState([]); - const [calendarValue, setCalendarValue] = useState(null); - const [inputNumberValue, setInputNumberValue] = useState(null); - const [chipsValue, setChipsValue] = useState([]); - const [sliderValue, setSliderValue] = useState(''); - const [ratingValue, setRatingValue] = useState(null); - const [colorValue, setColorValue] = useState('1976D2'); + const [autoFilteredValue, setAutoFilteredValue] = useState([]); + const [calendarValue, setCalendarValue] = useState(null); + const [inputNumberValue, setInputNumberValue] = useState(null); + const [chipsValue, setChipsValue] = useState([]); + const [sliderValue, setSliderValue] = useState(''); + const [ratingValue, setRatingValue] = useState(null); + const [colorValue, setColorValue] = useState('1976D2'); const [knobValue, setKnobValue] = useState(20); const [radioValue, setRadioValue] = useState(null); - const [checkboxValue, setCheckboxValue] = useState([]); + const [checkboxValue, setCheckboxValue] = useState([]); const [switchValue, setSwitchValue] = useState(false); const [listboxValue, setListboxValue] = useState(null); const [dropdownValue, setDropdownValue] = useState(null); @@ -49,8 +44,10 @@ const InputDemo: Page = () => { const [selectButtonValue1, setSelectButtonValue1] = useState(null); const [selectButtonValue2, setSelectButtonValue2] = useState(null); const [inputGroupValue, setInputGroupValue] = useState(false); + const [selectedNode, setSelectedNode] = useState(null); + const [treeSelectNodes, setTreeSelectNodes] = useState(null); - const listboxValues: InputValue[] = [ + const listboxValues = [ { name: 'New York', code: 'NY' }, { name: 'Rome', code: 'RM' }, { name: 'London', code: 'LDN' }, @@ -58,7 +55,7 @@ const InputDemo: Page = () => { { name: 'Paris', code: 'PRS' } ]; - const dropdownValues: InputValue[] = [ + const dropdownValues = [ { name: 'New York', code: 'NY' }, { name: 'Rome', code: 'RM' }, { name: 'London', code: 'LDN' }, @@ -66,7 +63,7 @@ const InputDemo: Page = () => { { name: 'Paris', code: 'PRS' } ]; - const multiselectValues: InputValue[] = [ + const multiselectValues = [ { name: 'Australia', code: 'AU' }, { name: 'Brazil', code: 'BR' }, { name: 'China', code: 'CN' }, @@ -79,23 +76,26 @@ const InputDemo: Page = () => { { name: 'United States', code: 'US' } ]; - const selectButtonValues1: InputValue[] = [ + const selectButtonValues1 = [ { name: 'Option 1', code: 'O1' }, { name: 'Option 2', code: 'O2' }, { name: 'Option 3', code: 'O3' } ]; - const selectButtonValues2: InputValue[] = [ + const selectButtonValues2 = [ { name: 'Option 1', code: 'O1' }, { name: 'Option 2', code: 'O2' }, { name: 'Option 3', code: 'O3' } ]; useEffect(() => { - CountryService.getCountries().then((data) => setAutoValue(data)); + const countryService = new CountryService(); + const nodeService = new NodeService(); + countryService.getCountries().then((data) => setAutoValue(data)); + nodeService.getTreeNodes().then((data) => setTreeSelectNodes(data)); }, []); - const searchCountry = (event: AutoCompleteCompleteEvent) => { + const searchCountry = (event) => { setTimeout(() => { if (!event.query.trim().length) { setAutoFilteredValue([...autoValue]); @@ -109,7 +109,7 @@ const InputDemo: Page = () => { }, 250); }; - const onCheckboxChange = (e: CheckboxChangeEvent) => { + const onCheckboxChange = (e) => { let selectedValue = [...checkboxValue]; if (e.checked) selectedValue.push(e.value); else selectedValue.splice(selectedValue.indexOf(e.value), 1); @@ -117,23 +117,17 @@ const InputDemo: Page = () => { setCheckboxValue(selectedValue); }; - const itemTemplate = (option: InputValue) => { + const itemTemplate = (option) => { return (
              - {option.name} (e.currentTarget.src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png')} - className={`flag flag-${option.code.toLowerCase()}`} - style={{ width: '21px' }} - /> - {option.name} + + {option.name}
              ); }; return ( -
              +
              InputText
              @@ -179,35 +173,35 @@ const InputDemo: Page = () => {
              Textarea
              - +
              AutoComplete
              setSelectedAutoValue(e.value)} suggestions={autoFilteredValue} completeMethod={searchCountry} field="name" />
              Calendar
              - setCalendarValue(e.value ?? null)} /> + setCalendarValue(e.value)}>
              InputNumber
              - setInputNumberValue(e.value ?? null)} showButtons mode="decimal"> + setInputNumberValue(e.value)} showButtons mode="decimal">
              Chips
              - setChipsValue(e.value ?? [])} /> + setChipsValue(e.value)} />
              Slider
              - setSliderValue(parseInt(e.target.value, 10))} /> - setSliderValue(e.value as number)} /> + setSliderValue(parseInt(e.target.value), 10)} /> + setSliderValue(e.value)} />
              Rating
              - setRatingValue(e.value ?? 0)} /> + setRatingValue(e.value)} />
              ColorPicker
              - setColorValue(e.value ?? '')} style={{ width: '2rem' }} /> + setColorValue(e.value)} style={{ width: '2rem' }} />
              Knob
              @@ -264,7 +258,7 @@ const InputDemo: Page = () => {
              Input Switch
              - setSwitchValue(e.value ?? false)} /> + setSwitchValue(e.value)} />
              @@ -279,13 +273,14 @@ const InputDemo: Page = () => { value={multiselectValue} onChange={(e) => setMultiselectValue(e.value)} options={multiselectValues} - itemTemplate={itemTemplate} optionLabel="name" placeholder="Select Countries" filter - className="multiselect-custom" display="chip" - /> + itemTemplate={itemTemplate} /> + +
              TreeSelect
              + setSelectedNode(e.value)} options={treeSelectNodes} placeholder="Select Item">
              @@ -337,7 +332,7 @@ const InputDemo: Page = () => {
              - setInputGroupValue(e.checked ?? false)} /> + setInputGroupValue(e.checked)} binary="true" />
              diff --git a/pages/uikit/invalidstate/index.js b/pages/uikit/invalidstate/index.js new file mode 100644 index 00000000..0c55d06d --- /dev/null +++ b/pages/uikit/invalidstate/index.js @@ -0,0 +1,113 @@ +import React, { useState, useEffect } from 'react'; +import { InputText } from 'primereact/inputtext'; +import { InputTextarea } from 'primereact/inputtextarea'; +import { InputMask } from 'primereact/inputmask'; +import { InputNumber } from 'primereact/inputnumber'; +import { AutoComplete } from 'primereact/autocomplete'; +import { Calendar } from 'primereact/calendar'; +import { Chips } from 'primereact/chips'; +import { Dropdown } from 'primereact/dropdown'; +import { MultiSelect } from 'primereact/multiselect'; +import { Password } from 'primereact/password'; +import { CountryService } from '../../../demo/service/CountryService'; + +const InvalidStateDemo = () => { + const [countries, setCountries] = useState([]); + const [filteredCountries, setFilteredCountries] = useState(null); + const [value1, setValue1] = useState(''); + const [value2, setValue2] = useState(null); + const [value3, setValue3] = useState(''); + const [value4, setValue4] = useState([]); + const [value5, setValue5] = useState(''); + const [value6, setValue6] = useState(''); + const [value7, setValue7] = useState(null); + const [value8, setValue8] = useState(null); + const [value9, setValue9] = useState(null); + const [value10, setValue10] = useState(''); + + const cities = [ + { name: 'New York', code: 'NY' }, + { name: 'Rome', code: 'RM' }, + { name: 'London', code: 'LDN' }, + { name: 'Istanbul', code: 'IST' }, + { name: 'Paris', code: 'PRS' } + ]; + + useEffect(() => { + const countryService = new CountryService(); + countryService.getCountries().then((countries) => { + setCountries(countries); + }); + }, []); + + const searchCountry = (event) => { + // in a real application, make a request to a remote url with the query and + // return filtered results, for demo we filter at client side + const filtered = []; + const query = event.query; + for (let i = 0; i < countries.length; i++) { + const country = countries[i]; + if (country.name.toLowerCase().indexOf(query.toLowerCase()) === 0) { + filtered.push(country); + } + } + setFilteredCountries(filtered); + }; + + return ( +
              +
              Invalid State
              +
              +
              +
              + + setValue1(e.target.value)} className="p-invalid" /> +
              +
              + + setValue2(e.value)} suggestions={filteredCountries} completeMethod={searchCountry} field="name" className="p-invalid" /> +
              +
              + + setValue3(e.value)} className="p-invalid" showIcon /> +
              +
              + + setValue4(e.value)} className="p-invalid" /> +
              +
              + + setValue5(e.target.value)} className="p-invalid" /> +
              +
              + +
              +
              + + setValue6(e.value)} className="p-invalid" /> +
              +
              + + setValue7(e.target.value)} className="p-invalid" /> +
              +
              + + setValue8(e.value)} optionLabel="name" className="p-invalid" /> +
              +
              + + setValue9(e.value)} optionLabel="name" className="p-invalid" /> +
              +
              + + setValue10(e.target.value)} className="p-invalid" /> +
              +
              +
              +
              + + + ); +}; + +export default InvalidStateDemo; diff --git a/app/(main)/uikit/list/page.tsx b/pages/uikit/list/index.js similarity index 75% rename from app/(main)/uikit/list/page.tsx rename to pages/uikit/list/index.js index 5885447a..8fb4b90a 100644 --- a/app/(main)/uikit/list/page.tsx +++ b/pages/uikit/list/index.js @@ -1,15 +1,13 @@ -'use client'; - import React, { useState, useEffect } from 'react'; import { DataView, DataViewLayoutOptions } from 'primereact/dataview'; import { Button } from 'primereact/button'; -import { Dropdown, DropdownChangeEvent } from 'primereact/dropdown'; +import { Dropdown } from 'primereact/dropdown'; import { Rating } from 'primereact/rating'; import { PickList } from 'primereact/picklist'; import { OrderList } from 'primereact/orderlist'; -import { ProductService } from '../../../../demo/service/ProductService'; +import { ProductService } from '../../../demo/service/ProductService'; import { InputText } from 'primereact/inputtext'; -import type { Demo } from '../../../../types/types'; +import getConfig from 'next/config'; const ListDemo = () => { const listValue = [ @@ -25,13 +23,14 @@ const ListDemo = () => { const [picklistSourceValue, setPicklistSourceValue] = useState(listValue); const [picklistTargetValue, setPicklistTargetValue] = useState([]); const [orderlistValue, setOrderlistValue] = useState(listValue); - const [dataViewValue, setDataViewValue] = useState([]); + const [dataViewValue, setDataViewValue] = useState(null); const [globalFilterValue, setGlobalFilterValue] = useState(''); - const [filteredValue, setFilteredValue] = useState(null); - const [layout, setLayout] = useState<'grid' | 'list' | (string & Record)>('grid'); + const [filteredValue, setFilteredValue] = useState(null); + const [layout, setLayout] = useState('grid'); const [sortKey, setSortKey] = useState(null); - const [sortOrder, setSortOrder] = useState<0 | 1 | -1 | null>(null); - const [sortField, setSortField] = useState(''); + const [sortOrder, setSortOrder] = useState(null); + const [sortField, setSortField] = useState(null); + const contextPath = getConfig().publicRuntimeConfig.contextPath; const sortOptions = [ { label: 'Price High to Low', value: '!price' }, @@ -39,32 +38,26 @@ const ListDemo = () => { ]; useEffect(() => { - ProductService.getProducts().then((data) => setDataViewValue(data)); - setGlobalFilterValue(''); - }, []); - - useEffect(() => { - ProductService.getProducts().then((data) => setDataViewValue(data)); + const productService = new ProductService(); + productService.getProducts().then((data) => setDataViewValue(data)); setGlobalFilterValue(''); }, []); - const onFilter = (e: React.ChangeEvent) => { + const onFilter = (e) => { const value = e.target.value; setGlobalFilterValue(value); if (value.length === 0) { setFilteredValue(null); - } else { - const filtered = dataViewValue?.filter((product) => { - const productNameLowercase = product.name.toLowerCase(); - const searchValueLowercase = value.toLowerCase(); - return productNameLowercase.includes(searchValueLowercase); + } + else { + const filtered = dataViewValue.filter((product) => { + return product.name.toLowerCase().includes(value); }); - setFilteredValue(filtered); } }; - const onSortChange = (event: DropdownChangeEvent) => { + const onSortChange = (event) => { const value = event.value; if (value.indexOf('!') === 0) { @@ -89,11 +82,11 @@ const ListDemo = () => {
              ); - const dataviewListItem = (data: Demo.Product) => { + const dataviewListItem = (data) => { return (
              - {data.name} + {data.name}
              {data.name}
              {data.description}
              @@ -105,15 +98,15 @@ const ListDemo = () => {
              ${data.price} - - {data.inventoryStatus} + + {data.inventoryStatus}
              ); }; - const dataviewGridItem = (data: Demo.Product) => { + const dataviewGridItem = (data) => { return (
              @@ -122,10 +115,10 @@ const ListDemo = () => { {data.category}
              - {data.inventoryStatus} + {data.inventoryStatus}
              - {data.name} + {data.name}
              {data.name}
              {data.description}
              @@ -139,7 +132,7 @@ const ListDemo = () => { ); }; - const itemTemplate = (data: Demo.Product, layout: 'grid' | 'list' | (string & Record)) => { + const itemTemplate = (data, layout) => { if (!data) { return; } @@ -152,7 +145,7 @@ const ListDemo = () => { }; return ( -
              +
              DataView
              @@ -182,7 +175,15 @@ const ListDemo = () => {
              OrderList
              -
              {item.name}
              } onChange={(e) => setOrderlistValue(e.value)}>
              +
              {item.name}
              } + onChange={(e) => setOrderlistValue(e.value)} + >
              diff --git a/app/(main)/uikit/media/page.tsx b/pages/uikit/media/index.js similarity index 62% rename from app/(main)/uikit/media/page.tsx rename to pages/uikit/media/index.js index 41e01ce0..47dd48a9 100644 --- a/app/(main)/uikit/media/page.tsx +++ b/pages/uikit/media/index.js @@ -1,17 +1,16 @@ -'use client'; - -import { Button } from 'primereact/button'; +import React, { useEffect, useState } from 'react'; import { Carousel } from 'primereact/carousel'; import { Galleria } from 'primereact/galleria'; +import { Button } from 'primereact/button'; import { Image } from 'primereact/image'; -import React, { useEffect, useState } from 'react'; -import { PhotoService } from '../../../../demo/service/PhotoService'; -import { ProductService } from '../../../../demo/service/ProductService'; -import type { Demo } from '../../../../types/types'; +import { ProductService } from '../../../demo/service/ProductService'; +import { PhotoService } from '../../../demo/service/PhotoService'; +import getConfig from 'next/config'; const MediaDemo = () => { - const [products, setProducts] = useState([]); - const [images, setImages] = useState([]); + const contextPath = getConfig().publicRuntimeConfig.contextPath; + const [products, setProducts] = useState([]); + const [images, setImages] = useState([]); const galleriaResponsiveOptions = [ { @@ -50,33 +49,35 @@ const MediaDemo = () => { ]; useEffect(() => { - ProductService.getProductsSmall().then((products) => setProducts(products)); + const productService = new ProductService(); + productService.getProductsSmall().then((products) => setProducts(products)); - PhotoService.getImages().then((images) => setImages(images)); + const photoService = new PhotoService(); + photoService.getImages().then((images) => setImages(images)); }, []); - const carouselItemTemplate = (product: Demo.Product) => { + const carouselItemTemplate = (product) => { return (
              - {product.name} + {product.name}

              {product.name}

              ${product.price}
              - {product.inventoryStatus} + {product.inventoryStatus}
              - - - + + +
              ); }; - const galleriaItemTemplate = (item: Demo.Photo) => {item.alt}; - const galleriaThumbnailTemplate = (item: Demo.Photo) => {item.alt}; + const galleriaItemTemplate = (item) => {item.alt}; + const galleriaThumbnailTemplate = (item) => {item.alt}; return (
              @@ -89,17 +90,17 @@ const MediaDemo = () => {
              -
              Image
              -
              - Image -
              +
              Galleria
              +
              -
              Galleria
              - +
              Image
              +
              + galleria +
              diff --git a/app/(main)/uikit/menu/confirmation/page.tsx b/pages/uikit/menu/confirmation.js similarity index 90% rename from app/(main)/uikit/menu/confirmation/page.tsx rename to pages/uikit/menu/confirmation.js index 8b5b8d2f..a42df050 100644 --- a/app/(main)/uikit/menu/confirmation/page.tsx +++ b/pages/uikit/menu/confirmation.js @@ -1,7 +1,5 @@ -'use client'; - import React from 'react'; -import Menu from '../page'; +import Menu from './index'; function ConfirmationDemo() { return ( diff --git a/app/(main)/uikit/menu/page.tsx b/pages/uikit/menu/index.js similarity index 94% rename from app/(main)/uikit/menu/page.tsx rename to pages/uikit/menu/index.js index c49836bd..27e50617 100644 --- a/app/(main)/uikit/menu/page.tsx +++ b/pages/uikit/menu/index.js @@ -1,4 +1,3 @@ -'use client'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { Menubar } from 'primereact/menubar'; import { InputText } from 'primereact/inputtext'; @@ -11,18 +10,15 @@ import { Button } from 'primereact/button'; import { ContextMenu } from 'primereact/contextmenu'; import { MegaMenu } from 'primereact/megamenu'; import { PanelMenu } from 'primereact/panelmenu'; -import { useRouter } from 'next/navigation'; -import { usePathname } from 'next/navigation'; +import { useRouter } from 'next/router'; -const MenuDemo = ({ children }: any) => { +const MenuDemo = ({ children }) => { const [activeIndex, setActiveIndex] = useState(0); - const menu = useRef(null); - const contextMenu = useRef(null); + const menu = useRef(null); + const contextMenu = useRef(null); const router = useRouter(); - const pathname = usePathname(); - const checkActiveIndex = useCallback(() => { - const paths = pathname.split('/'); + const paths = router.pathname.split('/'); const currentPath = paths[paths.length - 1]; switch (currentPath) { @@ -38,7 +34,7 @@ const MenuDemo = ({ children }: any) => { default: break; } - }, [pathname]); + }, [router]); useEffect(() => { checkActiveIndex(); @@ -128,10 +124,7 @@ const MenuDemo = ({ children }: any) => { { label: 'Personal', command: () => router.push('/uikit/menu') }, { label: 'Seat', command: () => router.push('/uikit/menu/seat') }, { label: 'Payment', command: () => router.push('/uikit/menu/payment') }, - { - label: 'Confirmation', - command: () => router.push('/uikit/menu/confirmation') - } + { label: 'Confirmation', command: () => router.push('/uikit/menu/confirmation') } ]; const tieredMenuItems = [ @@ -469,12 +462,12 @@ const MenuDemo = ({ children }: any) => { } ]; - const toggleMenu = (event: React.MouseEvent) => { - menu.current?.toggle(event); + const toggleMenu = (event) => { + menu.current.toggle(event); }; - const onContextRightClick = (event: React.MouseEvent) => { - contextMenu.current?.show(event); + const onContextRightClick = (event) => { + contextMenu.current.show(event); }; const menubarEndTemplate = () => { @@ -506,7 +499,7 @@ const MenuDemo = ({ children }: any) => {
              Steps
              setActiveIndex(e.index)} readOnly={false} /> - {pathname === '/uikit/menu' ? ( + {router.pathname === '/uikit/menu' ? (

              Personal Component Content via Child Route

              @@ -521,7 +514,7 @@ const MenuDemo = ({ children }: any) => {
              TabMenu
              setActiveIndex(e.index)} /> - {pathname === '/uikit/menu' ? ( + {router.pathname === '/uikit/menu' ? (

              Personal Component Content via Child Route

              @@ -557,17 +550,17 @@ const MenuDemo = ({ children }: any) => {
              ContextMenu
              Right click to display. - +
              MegaMenu - Horizontal
              - +
              MegaMenu - Vertical
              - +
              diff --git a/app/(main)/uikit/menu/payment/page.tsx b/pages/uikit/menu/payment.js similarity index 89% rename from app/(main)/uikit/menu/payment/page.tsx rename to pages/uikit/menu/payment.js index 4f19d0b7..61aa9783 100644 --- a/app/(main)/uikit/menu/payment/page.tsx +++ b/pages/uikit/menu/payment.js @@ -1,6 +1,5 @@ -'use client'; import React from 'react'; -import Menu from '../page'; +import Menu from './index'; function PaymentDemo() { return ( diff --git a/app/(main)/uikit/menu/seat/page.tsx b/pages/uikit/menu/seat.js similarity index 89% rename from app/(main)/uikit/menu/seat/page.tsx rename to pages/uikit/menu/seat.js index a4dd25cf..8b90d798 100644 --- a/app/(main)/uikit/menu/seat/page.tsx +++ b/pages/uikit/menu/seat.js @@ -1,7 +1,5 @@ -'use client'; - import React from 'react'; -import Menu from '../page'; +import Menu from './index'; function SeatDemo() { return ( diff --git a/app/(main)/uikit/message/page.tsx b/pages/uikit/message/index.js similarity index 72% rename from app/(main)/uikit/message/page.tsx rename to pages/uikit/message/index.js index 772cb852..04f95c7c 100644 --- a/app/(main)/uikit/message/page.tsx +++ b/pages/uikit/message/index.js @@ -1,4 +1,3 @@ -'use client'; import React, { useRef, useState } from 'react'; import { Toast } from 'primereact/toast'; import { Messages } from 'primereact/messages'; @@ -9,59 +8,39 @@ import { Button } from 'primereact/button'; const MessagesDemo = () => { const [username, setUsername] = useState(''); const [email, setEmail] = useState(''); - const toast = useRef(null); - const message = useRef(null); + const toast = useRef(); + const message = useRef(); const addSuccessMessage = () => { - message.current?.show({ severity: 'success', content: 'Message Detail' }); + message.current.show({ severity: 'success', content: 'Message Detail' }); }; const addInfoMessage = () => { - message.current?.show({ severity: 'info', content: 'Message Detail' }); + message.current.show({ severity: 'info', content: 'Message Detail' }); }; const addWarnMessage = () => { - message.current?.show({ severity: 'warn', content: 'Message Detail' }); + message.current.show({ severity: 'warn', content: 'Message Detail' }); }; const addErrorMessage = () => { - message.current?.show({ severity: 'error', content: 'Message Detail' }); + message.current.show({ severity: 'error', content: 'Message Detail' }); }; const showSuccess = () => { - toast.current?.show({ - severity: 'success', - summary: 'Success Message', - detail: 'Message Detail', - life: 3000 - }); + toast.current.show({ severity: 'success', summary: 'Success Message', detail: 'Message Detail', life: 3000 }); }; const showInfo = () => { - toast.current?.show({ - severity: 'info', - summary: 'Info Message', - detail: 'Message Detail', - life: 3000 - }); + toast.current.show({ severity: 'info', summary: 'Info Message', detail: 'Message Detail', life: 3000 }); }; const showWarn = () => { - toast.current?.show({ - severity: 'warn', - summary: 'Warn Message', - detail: 'Message Detail', - life: 3000 - }); + toast.current.show({ severity: 'warn', summary: 'Warn Message', detail: 'Message Detail', life: 3000 }); }; const showError = () => { - toast.current?.show({ - severity: 'error', - summary: 'Error Message', - detail: 'Message Detail', - life: 3000 - }); + toast.current.show({ severity: 'error', summary: 'Error Message', detail: 'Message Detail', life: 3000 }); }; return ( @@ -71,10 +50,10 @@ const MessagesDemo = () => {
              Toast
              -
              @@ -83,10 +62,10 @@ const MessagesDemo = () => {
              Messages
              -
              diff --git a/app/(main)/uikit/misc/page.tsx b/pages/uikit/misc/index.js similarity index 83% rename from app/(main)/uikit/misc/page.tsx rename to pages/uikit/misc/index.js index 92c72d8b..0974495f 100644 --- a/app/(main)/uikit/misc/page.tsx +++ b/pages/uikit/misc/index.js @@ -1,5 +1,3 @@ -'use client'; - import React, { useState, useEffect, useRef } from 'react'; import { ProgressBar } from 'primereact/progressbar'; import { Button } from 'primereact/button'; @@ -11,26 +9,32 @@ import { Chip } from 'primereact/chip'; import { Skeleton } from 'primereact/skeleton'; import { ScrollPanel } from 'primereact/scrollpanel'; import { ScrollTop } from 'primereact/scrolltop'; +import getConfig from 'next/config'; const MiscDemo = () => { const [value, setValue] = useState(0); - const intervalRef = useRef(null); + const interval = useRef(null); + const contextPath = getConfig().publicRuntimeConfig.contextPath; useEffect(() => { - const interval = setInterval(() => { - setValue((prevValue) => { - const newVal = prevValue + Math.floor(Math.random() * 10) + 1; - return newVal >= 100 ? 100 : newVal; - }); + let val = value; + interval.current = setInterval(() => { + val += Math.floor(Math.random() * 10) + 1; + + if (val >= 100) { + val = 100; + clearInterval(interval.current); + } + setValue(val); }, 2000); - intervalRef.current = interval; - return () => { - clearInterval(intervalRef.current as NodeJS.Timeout); - intervalRef.current = null; + if (interval.current) { + clearInterval(interval.current); + interval.current = null; + } }; - }, []); + }, [value]); return (
              @@ -77,7 +81,7 @@ const MiscDemo = () => { -
              @@ -93,11 +97,11 @@ const MiscDemo = () => {

              Avatar

              Avatar Group
              - - - - - + + + + + @@ -179,18 +183,18 @@ const MiscDemo = () => {
              Image
              - - - - + + + +
              Styling
              - - + +
              diff --git a/app/(main)/uikit/overlay/page.tsx b/pages/uikit/overlay/index.js similarity index 68% rename from app/(main)/uikit/overlay/page.tsx rename to pages/uikit/overlay/index.js index adf50b64..f9fffaf8 100644 --- a/app/(main)/uikit/overlay/page.tsx +++ b/pages/uikit/overlay/index.js @@ -1,19 +1,16 @@ -'use client'; - -import { Button } from 'primereact/button'; -import { Column } from 'primereact/column'; -import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup'; -import { DataTable, DataTableSelectEvent } from 'primereact/datatable'; +import React, { useState, useEffect, useRef } from 'react'; import { Dialog } from 'primereact/dialog'; -import { InputText } from 'primereact/inputtext'; -import { OverlayPanel } from 'primereact/overlaypanel'; +import { Button } from 'primereact/button'; import { Sidebar } from 'primereact/sidebar'; import { Toast } from 'primereact/toast'; -import React, { useEffect, useRef, useState } from 'react'; -import { ProductService } from '../../../../demo/service/ProductService'; -import type { Demo } from '../../../../types/types'; +import { Column } from 'primereact/column'; +import { DataTable } from 'primereact/datatable'; +import { OverlayPanel } from 'primereact/overlaypanel'; +import { InputText } from 'primereact/inputtext'; +import { confirmPopup, ConfirmPopup } from 'primereact/confirmpopup'; +import { ProductService } from '../../../demo/service/ProductService'; +import getConfig from 'next/config'; -type ButtonEvent = React.MouseEvent; const OverlayDemo = () => { const [displayBasic, setDisplayBasic] = useState(false); const [displayConfirmation, setDisplayConfirmation] = useState(false); @@ -22,31 +19,22 @@ const OverlayDemo = () => { const [visibleTop, setVisibleTop] = useState(false); const [visibleBottom, setVisibleBottom] = useState(false); const [visibleFullScreen, setVisibleFullScreen] = useState(false); - const [products, setProducts] = useState([]); - const [selectedProduct, setSelectedProduct] = useState(null); - const op = useRef(null); - const op2 = useRef(null); - const toast = useRef(null); + const [products, setProducts] = useState(null); + const [selectedProduct, setSelectedProduct] = useState(null); + const op = useRef(null); + const op2 = useRef(null); + const toast = useRef(null); + const contextPath = getConfig().publicRuntimeConfig.contextPath; const accept = () => { - toast.current?.show({ - severity: 'info', - summary: 'Confirmed', - detail: 'You have accepted', - life: 3000 - }); + toast.current.show({ severity: 'info', summary: 'Confirmed', detail: 'You have accepted', life: 3000 }); }; const reject = () => { - toast.current?.show({ - severity: 'error', - summary: 'Rejected', - detail: 'You have rejected', - life: 3000 - }); + toast.current.show({ severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000 }); }; - const confirm = (event: React.MouseEvent) => { + const confirm = (event) => { confirmPopup({ target: event.currentTarget, message: 'Are you sure you want to proceed?', @@ -57,55 +45,34 @@ const OverlayDemo = () => { }; useEffect(() => { - ProductService.getProductsSmall().then((data) => setProducts(data)); + const productService = new ProductService(); + productService.getProductsSmall().then((data) => setProducts(data)); }, []); - const toggle = (event: ButtonEvent) => { - op.current?.toggle(event); + const toggle = (event) => { + op.current.toggle(event); }; - const toggleDataTable = (event: ButtonEvent) => { - op2.current?.toggle(event); + const toggleDataTable = (event) => { + op2.current.toggle(event); }; - const formatCurrency = (value: number) => { - return value.toLocaleString('en-US', { - style: 'currency', - currency: 'USD' - }); + const formatCurrency = (value) => { + return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); }; - const onProductSelect = (event: DataTableSelectEvent) => { - op2.current?.hide(); - toast.current?.show({ - severity: 'info', - summary: 'Product Selected', - detail: event.data.name, - life: 3000 - }); - }; - - const onSelectionChange = (e: any): void => { - setSelectedProduct(e.value as Demo.Product); + const onProductSelect = (event) => { + op2.current.hide(); + toast.current.show({ severity: 'info', summary: 'Product Selected', detail: event.data.name, life: 3000 }); }; - const basicDialogFooter =
              @@ -133,15 +100,15 @@ const OverlayDemo = () => {
              Overlay Panel
              -
              -
              diff --git a/app/(main)/uikit/panel/page.tsx b/pages/uikit/panel/index.js similarity index 92% rename from app/(main)/uikit/panel/page.tsx rename to pages/uikit/panel/index.js index 5a852b75..c332254f 100644 --- a/app/(main)/uikit/panel/page.tsx +++ b/pages/uikit/panel/index.js @@ -1,5 +1,3 @@ -'use client'; - import React, { useRef } from 'react'; import { Toolbar } from 'primereact/toolbar'; import { Button } from 'primereact/button'; @@ -12,10 +10,11 @@ import { Card } from 'primereact/card'; import { Divider } from 'primereact/divider'; import { InputText } from 'primereact/inputtext'; import { Splitter, SplitterPanel } from 'primereact/splitter'; +import { Password } from 'primereact/password'; import { Menu } from 'primereact/menu'; const PanelDemo = () => { - const menu1 = useRef(null); + const menu1 = useRef(null); const toolbarItems = [ { label: 'Save', @@ -39,13 +38,13 @@ const PanelDemo = () => { return ( <> +

              @@ -211,15 +210,21 @@ const PanelDemo = () => {

              Splitter
              -
              Panel 1
              +
              + Panel 1 +
              -
              Panel 2
              +
              + Panel 2 +
              -
              Panel 3
              +
              + Panel 3 +
              diff --git a/app/(main)/uikit/table/page.tsx b/pages/uikit/table/index.js similarity index 71% rename from app/(main)/uikit/table/page.tsx rename to pages/uikit/table/index.js index 90c307bb..0ae3b75f 100644 --- a/app/(main)/uikit/table/page.tsx +++ b/pages/uikit/table/index.js @@ -1,36 +1,36 @@ -'use client'; -import { CustomerService } from '../../../../demo/service/CustomerService'; -import { ProductService } from '../../../../demo/service/ProductService'; +import React, { useState, useEffect, useRef } from 'react'; +import { classNames } from 'primereact/utils'; import { FilterMatchMode, FilterOperator } from 'primereact/api'; -import { Button } from 'primereact/button'; -import { Calendar } from 'primereact/calendar'; -import { Column, ColumnFilterApplyTemplateOptions, ColumnFilterClearTemplateOptions, ColumnFilterElementTemplateOptions } from 'primereact/column'; -import { DataTable, DataTableExpandedRows, DataTableFilterMeta } from 'primereact/datatable'; +import { DataTable } from 'primereact/datatable'; +import { Column } from 'primereact/column'; import { Dropdown } from 'primereact/dropdown'; import { InputNumber } from 'primereact/inputnumber'; -import { InputText } from 'primereact/inputtext'; -import { MultiSelect } from 'primereact/multiselect'; +import { Button } from 'primereact/button'; import { ProgressBar } from 'primereact/progressbar'; -import { Rating } from 'primereact/rating'; +import { Calendar } from 'primereact/calendar'; +import { MultiSelect } from 'primereact/multiselect'; import { Slider } from 'primereact/slider'; -import { ToggleButton } from 'primereact/togglebutton'; import { TriStateCheckbox } from 'primereact/tristatecheckbox'; -import { classNames } from 'primereact/utils'; -import React, { useEffect, useState } from 'react'; -import type { Demo } from '../../../../types/types'; +import { ToggleButton } from 'primereact/togglebutton'; +import { Rating } from 'primereact/rating'; +import { CustomerService } from '../../../demo/service/CustomerService'; +import { ProductService } from '../../../demo/service/ProductService'; +import getConfig from 'next/config'; +import { InputText } from 'primereact/inputtext'; const TableDemo = () => { - const [customers1, setCustomers1] = useState([]); - const [customers2, setCustomers2] = useState([]); - const [customers3, setCustomers3] = useState([]); - const [filters1, setFilters1] = useState({}); + const [customers1, setCustomers1] = useState(null); + const [customers2, setCustomers2] = useState([]); + const [customers3, setCustomers3] = useState([]); + const [filters1, setFilters1] = useState(null); const [loading1, setLoading1] = useState(true); const [loading2, setLoading2] = useState(true); const [idFrozen, setIdFrozen] = useState(false); - const [products, setProducts] = useState([]); + const [products, setProducts] = useState([]); const [globalFilterValue1, setGlobalFilterValue1] = useState(''); - const [expandedRows, setExpandedRows] = useState([]); + const [expandedRows, setExpandedRows] = useState(null); const [allExpanded, setAllExpanded] = useState(false); + const contextPath = getConfig().publicRuntimeConfig.contextPath; const representatives = [ { name: 'Amy Elsner', image: 'amyelsner.png' }, @@ -47,14 +47,17 @@ const TableDemo = () => { const statuses = ['unqualified', 'qualified', 'new', 'negotiation', 'renewal', 'proposal']; + const customerService = new CustomerService(); + const productService = new ProductService(); + const clearFilter1 = () => { initFilters1(); }; - const onGlobalFilterChange1 = (e: React.ChangeEvent) => { + const onGlobalFilterChange1 = (e) => { const value = e.target.value; let _filters1 = { ...filters1 }; - (_filters1['global'] as any).value = value; + _filters1['global'].value = value; setFilters1(_filters1); setGlobalFilterValue1(value); @@ -63,7 +66,7 @@ const TableDemo = () => { const renderHeader1 = () => { return (
              - ; + const filterClearTemplate = (options) => { + return ; }; - const filterApplyTemplate = (options: ColumnFilterApplyTemplateOptions) => { - return ; + const filterApplyTemplate = (options) => { + return ; }; - const representativeBodyTemplate = (rowData: Demo.Customer) => { + const representativeBodyTemplate = (rowData) => { const representative = rowData.representative; return ( {representative.name} ((e.target as HTMLImageElement).src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png')} + src={`${contextPath}/demo/images/avatar/${representative.image}`} + onError={(e) => (e.target.src = 'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png')} width={32} style={{ verticalAlign: 'middle' }} /> @@ -182,7 +167,7 @@ const TableDemo = () => { ); }; - const representativeFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { + const representativeFilterTemplate = (options) => { return ( <>
              Agent Picker
              @@ -191,48 +176,48 @@ const TableDemo = () => { ); }; - const representativesItemTemplate = (option: any) => { + const representativesItemTemplate = (option) => { return (
              - {option.name} + {option.name} {option.name}
              ); }; - const dateBodyTemplate = (rowData: Demo.Customer) => { + const dateBodyTemplate = (rowData) => { return formatDate(rowData.date); }; - const dateFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { + const dateFilterTemplate = (options) => { return options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />; }; - const balanceBodyTemplate = (rowData: Demo.Customer) => { - return formatCurrency(rowData.balance as number); + const balanceBodyTemplate = (rowData) => { + return formatCurrency(rowData.balance); }; - const balanceFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { + const balanceFilterTemplate = (options) => { return options.filterCallback(e.value, options.index)} mode="currency" currency="USD" locale="en-US" />; }; - const statusBodyTemplate = (rowData: Demo.Customer) => { + const statusBodyTemplate = (rowData) => { return {rowData.status}; }; - const statusFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { + const statusFilterTemplate = (options) => { return options.filterCallback(e.value, options.index)} itemTemplate={statusItemTemplate} placeholder="Select a Status" className="p-column-filter" showClear />; }; - const statusItemTemplate = (option: any) => { + const statusItemTemplate = (option) => { return {option}; }; - const activityBodyTemplate = (rowData: Demo.Customer) => { + const activityBodyTemplate = (rowData) => { return ; }; - const activityFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { + const activityFilterTemplate = (options) => { return ( options.filterCallback(e.value)} range className="m-3"> @@ -244,18 +229,11 @@ const TableDemo = () => { ); }; - const verifiedBodyTemplate = (rowData: Demo.Customer) => { - return ( - - ); + const verifiedBodyTemplate = (rowData) => { + return ; }; - const verifiedFilterTemplate = (options: ColumnFilterElementTemplateOptions) => { + const verifiedFilterTemplate = (options) => { return options.filterCallback(e.value)} />; }; @@ -265,7 +243,7 @@ const TableDemo = () => { }; const expandAll = () => { - let _expandedRows = {} as { [key: string]: boolean }; + let _expandedRows = {}; products.forEach((p) => (_expandedRows[`${p.id}`] = true)); setExpandedRows(_expandedRows); @@ -273,39 +251,39 @@ const TableDemo = () => { }; const collapseAll = () => { - setExpandedRows([]); + setExpandedRows(null); setAllExpanded(false); }; - const amountBodyTemplate = (rowData: Demo.Customer) => { - return formatCurrency(rowData.amount as number); + const amountBodyTemplate = (rowData) => { + return formatCurrency(rowData.amount); }; - const statusOrderBodyTemplate = (rowData: Demo.Customer) => { - return {rowData.status}; + const statusOrderBodyTemplate = (rowData) => { + return {rowData.status}; }; const searchBodyTemplate = () => { return