diff --git a/next.config.js b/next.config.js index a843cbe..7ff5e19 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,14 @@ /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, -} + images: { + remotePatterns: [ + { + protocol: "https", + hostname: "wordpress-1110286-3894329.cloudwaysapps.com", + }, + ], + }, +}; -module.exports = nextConfig +module.exports = nextConfig; diff --git a/package-lock.json b/package-lock.json index d7ba246..0bb5743 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,12 +38,17 @@ "react-dom": "18.2.0", "react-redux": "^8.1.2", "react-responsive": "^9.0.2", + "react-slick": "^0.29.0", "redux-logger": "^3.0.6", + "slick-carousel": "^1.8.1", "tailwind-merge": "^1.14.0", "tailwindcss": "3.3.3", "tailwindcss-animate": "^1.0.7", "three": "^0.156.1", "typescript": "5.2.2" + }, + "devDependencies": { + "@types/react-slick": "^0.23.10" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -1184,6 +1189,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-slick": { + "version": "0.23.10", + "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.10.tgz", + "integrity": "sha512-ZiqdencANDZy6sWOWJ54LDvebuXFEhDlHtXU9FFipQR2BcYU2QJxZhvJPW6YK7cocibUiNn+YvDTbt1HtCIBVA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/redux-logger": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/@types/redux-logger/-/redux-logger-3.0.9.tgz", @@ -1863,6 +1877,11 @@ "url": "https://joebell.co.uk" } }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -2152,6 +2171,11 @@ "node": ">=10.13.0" } }, + "node_modules/enquire.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz", + "integrity": "sha512-/KujNpO+PT63F7Hlpu4h3pE3TokKRHN26JYmQpPyjkRD/N57R7bPDNojMXdi7uveAKjYB7yQnartCxZnFWr0Xw==" + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -3575,6 +3599,12 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "peer": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3606,6 +3636,14 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "dependencies": { + "string-convert": "^0.2.0" + } + }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -3701,6 +3739,11 @@ "resolved": "https://registry.npmjs.org/lodash.clamp/-/lodash.clamp-4.0.3.tgz", "integrity": "sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg==" }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4577,6 +4620,22 @@ "react": ">=16.8.0" } }, + "node_modules/react-slick": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.29.0.tgz", + "integrity": "sha512-TGdOKE+ZkJHHeC4aaoH85m8RnFyWqdqRfAGkhd6dirmATXMZWAxOpTLmw2Ll/jPTQ3eEG7ercFr/sbzdeYCJXA==", + "dependencies": { + "classnames": "^2.2.5", + "enquire.js": "^2.1.6", + "json2mq": "^0.2.0", + "lodash.debounce": "^4.0.8", + "resize-observer-polyfill": "^1.5.0" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -4707,6 +4766,11 @@ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, "node_modules/resolve": { "version": "1.22.6", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", @@ -4894,6 +4958,14 @@ "node": ">=8" } }, + "node_modules/slick-carousel": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/slick-carousel/-/slick-carousel-1.8.1.tgz", + "integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==", + "peerDependencies": { + "jquery": ">=1.8.0" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -4920,6 +4992,11 @@ "node": ">=10.0.0" } }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" + }, "node_modules/string.prototype.codepointat": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", diff --git a/package.json b/package.json index 8576520..5c4efeb 100644 --- a/package.json +++ b/package.json @@ -39,11 +39,16 @@ "react-dom": "18.2.0", "react-redux": "^8.1.2", "react-responsive": "^9.0.2", + "react-slick": "^0.29.0", "redux-logger": "^3.0.6", + "slick-carousel": "^1.8.1", "tailwind-merge": "^1.14.0", "tailwindcss": "3.3.3", "tailwindcss-animate": "^1.0.7", "three": "^0.156.1", "typescript": "5.2.2" + }, + "devDependencies": { + "@types/react-slick": "^0.23.10" } } diff --git a/src/lib/redux/middleware.ts b/src/lib/redux/middleware.ts index cfc43a3..c4b7df7 100644 --- a/src/lib/redux/middleware.ts +++ b/src/lib/redux/middleware.ts @@ -1,10 +1,12 @@ /* Core */ import { pagesApi } from '@/services/pages' +import { portfolioApi } from '@/services/portfolio' import { postsApi } from '@/services/posts' const middleware = [ postsApi.middleware, pagesApi.middleware, + portfolioApi.middleware, ] export { middleware } \ No newline at end of file diff --git a/src/lib/redux/rootReducer.ts b/src/lib/redux/rootReducer.ts index 62cc8ee..37c52fe 100644 --- a/src/lib/redux/rootReducer.ts +++ b/src/lib/redux/rootReducer.ts @@ -1,7 +1,9 @@ import { pagesApi } from "@/services/pages"; +import { portfolioApi } from "@/services/portfolio"; import { postsApi } from "@/services/posts"; export const reducer = { [postsApi.reducerPath]: postsApi.reducer, [pagesApi.reducerPath]: pagesApi.reducer, + [portfolioApi.reducerPath]: portfolioApi.reducer, }; \ No newline at end of file diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index c7f25f8..b2e5c73 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -2,6 +2,8 @@ import { wrapper } from "@/lib/redux"; import { Provider } from "react-redux"; import type { AppProps } from "next/app"; import { Analytics } from "@vercel/analytics/react"; +import "slick-carousel/slick/slick.css"; +import "slick-carousel/slick/slick-theme.css"; import "@/styles/globals.css"; import { config } from "@fortawesome/fontawesome-svg-core"; diff --git a/src/pages/blog/[slug]/index.tsx b/src/pages/blog/[slug]/index.tsx index e7e52ac..98678fb 100644 --- a/src/pages/blog/[slug]/index.tsx +++ b/src/pages/blog/[slug]/index.tsx @@ -20,16 +20,6 @@ export const getStaticPaths = async () => { }; }; -const addRevalidateAndRedux = async ( - props: any, - reduxStaticProps: any, - revalidateSeconds = 50 -) => { - const getStaticProps = await reduxStaticProps(props); - getStaticProps.revalidate = revalidateSeconds; - return getStaticProps; -}; - export const getStaticProps = wrapper.getStaticProps( (store) => async (context) => { store.dispatch(getPost.initiate(context?.params?.slug)); diff --git a/src/pages/portfolio/index.tsx b/src/pages/portfolio/index.tsx new file mode 100644 index 0000000..b2f3fd1 --- /dev/null +++ b/src/pages/portfolio/index.tsx @@ -0,0 +1,109 @@ +import Link from "next/link"; +import parser from "html-react-parser"; +import Slider from "react-slick"; + +import { + getProjects, + getRunningQueriesThunk, + useGetProjectQuery, +} from "@/services/portfolio"; +import { wrapper } from "@/lib/redux"; +import Internal from "@/components/common/Internal"; +import { useCallback, useEffect, useRef, useState } from "react"; +import Image from "next/image"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faArrowLeft, faArrowRight } from "@fortawesome/free-solid-svg-icons"; + +export const getStaticProps = wrapper.getStaticProps( + (store) => async (context) => { + store.dispatch(getProjects.initiate()); + const [projects] = await Promise.all( + store.dispatch(getRunningQueriesThunk()) + ); + + return { + props: { + projects: projects.data, + }, + revalidate: 50, + }; + } +); + +export default function Portfolio({ projects }: any): JSX.Element { + const [selectedID, setSelectedID] = useState(""); + const [carouselChange, setCarouselChange] = useState(0); + const { data: project, isLoading } = useGetProjectQuery(selectedID); + const customSlider = useRef(); + const [sliderSettings, setSliderSettings] = useState({ + adaptiveHeight: true, + speed: 500, + slidesToShow: 1, + slidesToScroll: 1, + centerMode: true, + beforeChange: (current: any, next: any) => { + setCarouselChange(current); + }, + }); + + const nextSlide = () => customSlider.current.slickNext(); + const previousSlide = () => customSlider.current.slickPrev(); + + useEffect(() => { + const element = document.getElementsByClassName("slick-current")[0]; + const ID = element.querySelector("img")?.dataset.projectid; + setSelectedID(ID); + }, [carouselChange]); + + console.log(project); + return ( + +
+ {/* + // @ts-ignore */} + + {projects.map(({ id, acm_fields }: any) => ( +
+ {acm_fields?.featured_media?.alt_text} +
+ ))} +
+
+

+ {project?.acm_fields?.title} +
+ + +
+

+
+ {!isLoading ? parser(project?.acm_fields?.portfolioContent) : null} +
+
+
+
+ ); +} diff --git a/src/services/portfolio.ts b/src/services/portfolio.ts new file mode 100644 index 0000000..9b2fa4c --- /dev/null +++ b/src/services/portfolio.ts @@ -0,0 +1,28 @@ +import { WORDPRESS_BASE_API } from '@/utils/common-utils'; +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; +import { HYDRATE } from 'next-redux-wrapper'; + +export const portfolioApi: any = createApi({ + reducerPath: 'portfolio', + baseQuery: fetchBaseQuery({ baseUrl: WORDPRESS_BASE_API }), + extractRehydrationInfo(action, { reducerPath }) { + if(action.type === HYDRATE) { + return action.payload[reducerPath] + } + }, + tagTypes: ['Portfolio'], + endpoints: (builder) => ({ + getProjects: builder.query({ + query: () => `/projects`, + providesTags: ['Portfolio'], + }), + getProject: builder.query({ + query: (id) => `/projects/${id}`, + providesTags: ['Portfolio'], + }) + }) +}); + +export const { useGetProjectsQuery, useGetProjectQuery, util: { getRunningQueriesThunk } } = portfolioApi; + +export const { getProjects, getProject } = portfolioApi.endpoints; \ No newline at end of file