Skip to content
This repository has been archived by the owner on Jan 19, 2024. It is now read-only.

Commit

Permalink
Add kick off for dating site
Browse files Browse the repository at this point in the history
  • Loading branch information
jakub.sedlacek2 committed Oct 29, 2023
1 parent ecf30b6 commit 6780963
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 28 deletions.
4 changes: 4 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ const nextConfig = {
source: "/lovereport/shrnuti",
destination: "/lovereport/summary",
},
{
source: "/seznamka",
destination: "/dating-site"
}
];
},
images: {
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/friends/friends.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ export const getFriends = async (options: Record<string, unknown>, requestParams
// TODO: log error
return;
}
};
};
20 changes: 19 additions & 1 deletion src/app/api/member/member.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface IMemberResponse {
roles?: unknown[]; // Roles assigned to the member.
capabilities?: Record<string, unknown>; // All capabilities assigned to the member.
extra_capabilities?: Record<string, unknown>; // All capabilities assigned to the member.
xprofile?: unknown[]; // Member xProfile groups and its fields.
xprofile?: Xprofile; // Member xProfile groups and its fields.
friendship_status?: boolean; // Whether the logged in user has a friendship relationship with the fetched user.
friendship_status_slug?: "is_friend" | "not_friends" | "pending" | "awaiting_response"; // Slug of the friendship relationship status the logged in user has with the fetched user.
last_activity?: Record<string, unknown>; // Last date the member was active on the site (object properties: timediff, date and date_gmt).
Expand All @@ -25,7 +25,25 @@ export interface IMemberResponse {
thumb: string;
}; // Avatar URLs for the member (Full & Thumb sizes)
}
export type Xprofile = {
groups: { [key: string]: Group };
}

export type Group = {
name: string;
fields: { [key: string]: Field };
}

export type Field = {
name: string;
value: Value;
}

export type Value = {
raw: string;
unserialized: string[];
rendered: string;
}
/**
* GET /buddypress/v1/members
* https://developer.buddypress.org/bp-rest-api/reference/members/#list-members
Expand Down
11 changes: 2 additions & 9 deletions src/app/api/profile-field/basic-info/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getMemberById } from "app/api/member/member";
import { getServerSession } from "next-auth";
import { NextResponse } from "next/server";
import { getProfileFields } from "../profileField";
import { getCompletionPercents, getFieldValueFromArray } from "helpers/profileFieldHelpers";
import { calculateAge, getCompletionPercents, getFieldValueFromArray, safeUrl } from "helpers/profileFieldHelpers";
import { NextApiRequest } from "next";

export async function GET(request: NextApiRequest): Promise<Response> {
Expand Down Expand Up @@ -42,19 +42,12 @@ export const getUserBasicInfo = async (userId: number): Promise<UserBasicInfo |
region: getFieldValueFromArray(profileFields, "Kraj"),
status: getFieldValueFromArray(profileFields, "Status"),
profileComplete: getCompletionPercents(profileFields),
photo: member?.avatar_urls?.full ?? ''
// photo: userPhoto,
photo: safeUrl(member?.avatar_urls?.full ?? '')
};

return user;
};

const calculateAge = (birthday: any) => {
// birthday is a date
var ageDifMs = Date.now() - birthday;
var ageDate = new Date(ageDifMs); // miliseconds from epoch
return Math.abs(ageDate.getUTCFullYear() - 1970);
};

export type UserBasicInfo = {
nickname: string;
Expand Down
72 changes: 72 additions & 0 deletions src/app/dating-site/components/DatingSiteContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"use client";
import { Field, IMemberResponse } from "app/api/member/member.type";
import { calculateAge, safeUrl } from "helpers/profileFieldHelpers";
import Content from "library/atoms/Content";
import UserCard from "library/molecules/cards/UserCard";
import { createContext, useContext, useState } from "react";

type DatingSiteState = {
gender: string | null;
useMyPreferences: boolean;
data: IMemberResponse[];
};

type Props = { state: DatingSiteState; setState: (state: DatingSiteState) => void };

const DatingSiteContext = createContext<Props>({} as Props);

const DatingSiteContainer = (props: { members: IMemberResponse[] }) => {
const [state, setState] = useState<DatingSiteState>({
gender: null,
useMyPreferences: true,
data: props.members,
});

return (
<DatingSiteContext.Provider value={{ state, setState }}>
<Content title="Seznamka">
<DatingSiteFilter></DatingSiteFilter>
<h4>Našli jsme pro tebe</h4>
<DatingSiteResult></DatingSiteResult>
</Content>
</DatingSiteContext.Provider>
);
};

const getFieldValue = (fields: Field[], name: string) => {
return fields.find(e => e.name === name)?.value.raw ?? '---';
}

const DatingSiteResult = () => {
const { state, setState } = useContext<Props>(DatingSiteContext);

return (
<div>
{state.data.map(e => {

if(!e.xprofile) {
return <></>;
}

const fields = Object.values(e.xprofile.groups).flatMap(v => Object.values(v.fields));
const birthdate = getFieldValue(fields, 'Věk');
return (<UserCard
age={birthdate !== '' ? calculateAge(new Date(birthdate)) : 0}
name={e.name}
cardType="default"
gender={getFieldValue(fields, 'Pohlaví')}
location={`${getFieldValue(fields, 'Město')}, ${getFieldValue(fields, 'Kraj')}`}
userIsActive={false}
status={getFieldValue(fields, 'Status')}
photo={safeUrl(e.avatar_urls?.full ?? '')}
></UserCard>);
})}
</div>
);
};

const DatingSiteFilter = () => {
return <div></div>;
};

export default DatingSiteContainer;
22 changes: 22 additions & 0 deletions src/app/dating-site/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { getServerSession } from "next-auth";
import { getMembers } from "../api/member/member";
import DatingSiteContainer from "./components/DatingSiteContainer";
import { authOptions } from "app/api/auth/[...nextauth]/route";
import { redirect } from "next/navigation";

const DatingSitePage = async () => {

const session = await getServerSession(authOptions)

if(!session) {
redirect("/");
}

const members = await getMembers({}, {
type: "random",
});

return (<DatingSiteContainer members={members ?? []}></DatingSiteContainer>);
}

export default DatingSitePage;
7 changes: 1 addition & 6 deletions src/components/home/HomeLoggedIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { SignOutSvg } from "library/icons/actions";
import { signOut } from "next-auth/react";
import { UserBasicInfo } from "app/api/profile-field/basic-info/route";
import { IMemberResponse } from "app/api/member/member.type";
import { safeUrl } from "helpers/profileFieldHelpers";

//Zkušební data
const getCards = (friends: { items: Friend[], pending: number}) => [
Expand Down Expand Up @@ -138,12 +139,6 @@ const HomeLoggedIn = (props: Props) => {
);
};

function safeUrl(value: string) {
if (value.startsWith("http")) {
return value;
}

return "https://" + value;
}

export default HomeLoggedIn;
22 changes: 22 additions & 0 deletions src/helpers/profileFieldHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,25 @@ export const getCompletionPercents = (fields: ProfileFieldResponse[]): number =>
export const getFieldValueFromArray = (array: ProfileFieldResponse[], name: string): string => {
return getValueFromProfileField(getProfileFieldFromArray(array, name));
};


export const calculateAge = (birthday: any): number => {
// birthday is a date
let ageDifMs = Date.now() - birthday;
let ageDate = new Date(ageDifMs); // miliseconds from epoch
let result = Math.abs(ageDate.getUTCFullYear() - 1970);

if(isNaN(result)) {
return 0;
}

return result;
};

export const safeUrl = (value: string) => {
if (value.startsWith("http")) {
return value;
}

return "https://" + value;
}
14 changes: 14 additions & 0 deletions src/library/atoms/ProfileStatus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { HeartSvg } from "library/icons/symbols";

const ProfileStatus = (props: {status: string}) => {
return (<div className="flex gap-2 items-center">
{props.status === "seznamuji se" && (
<span className="text-magenta-40">
<HeartSvg width={20} />
</span>
)}
<p>{props.status}</p>
</div>);
}

export default ProfileStatus;
10 changes: 2 additions & 8 deletions src/library/molecules/cards/ProfileCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import classNames from "helpers/classNames";
import Button from "library/atoms/Button";
import CardContainer from "library/atoms/CardContainer";
import Divider from "library/atoms/Divider";
import ProfileStatus from "library/atoms/ProfileStatus";
import Tag from "library/atoms/Tag";
import TextLink from "library/atoms/TextLink";
import { AddFriendSvg, EditProfileSvg, RemoveSvg, SendMessageSvg } from "library/icons/actions";
Expand Down Expand Up @@ -48,14 +49,7 @@ const ProfileCard = ({ name, nickname, gender, age, location, status, tags, clas
<p>{gender}</p>
<p>{age} let</p>
<p>{location}</p>
<div className="flex gap-2 items-center">
{status === "seznamuji se" && (
<span className="text-magenta-40">
<HeartSvg width={20} />
</span>
)}
<p>{status}</p>
</div>
<ProfileStatus status={status}></ProfileStatus>
<div className="flex flex-wrap gap-2 mt-3">
{tags.map((tag, index) => {
return <Tag key={index} title={tag} variant="light" className="col-span-1" />;
Expand Down
9 changes: 6 additions & 3 deletions src/library/molecules/cards/UserCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"use client";

import { stat } from "fs";
import classNames from "helpers/classNames";
import Button from "library/atoms/Button";
import CardContainer from "library/atoms/CardContainer";
import ProfileStatus from "library/atoms/ProfileStatus";
import TextLink from "library/atoms/TextLink";
import { AddFriendSvg, RemoveSvg, SendMessageSvg } from "library/icons/actions";
import { ShakingHandsSvg } from "library/icons/symbols";
Expand All @@ -16,9 +18,10 @@ type Props = {
location: string;
photo: string;
userIsActive: boolean;
status?: string;
};

const UserCard = ({ cardType, name, gender, age, location, photo, userIsActive }: Props) => {
const UserCard = ({ cardType, name, gender, age, location, photo, userIsActive, status }: Props) => {
const userActivity = (
<>
<div className="flex items-center gap-2 text-gray-70 font-normal">
Expand All @@ -41,13 +44,13 @@ const UserCard = ({ cardType, name, gender, age, location, photo, userIsActive }
return cardType === "default" ? (
<CardContainer variant="bubble" padding="smaller" className="flex items-center gap-4 ">
<div className="flex-grow">
<h5 className="mb-1">{name}</h5>
<h5 className="mb-1">@{name}</h5>
<div className="text-gray-70 font-normal">
<p>
{gender}, {age} let
</p>
<p>{location}</p>
{userActivity}
<ProfileStatus status={status ?? ''}></ProfileStatus>
</div>
</div>
<div className="relative">
Expand Down

0 comments on commit 6780963

Please sign in to comment.