Skip to content

Commit

Permalink
More details in metadata (show) card (#1253)
Browse files Browse the repository at this point in the history
* fea(website): more consistent logging

* chore(website): change order of imports

* feat(backend): change name of stuff

* chore(frontend): adapt to new gql schema

* refactor(frontend): start to display next progress

* feat(frontend): display show in progress

* feat(frontend): display next episode if current not in progress

* fix(frontend): do not display left label in calendar page
  • Loading branch information
IgnisDa authored Feb 13, 2025
1 parent 049862e commit b15244d
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 66 deletions.
57 changes: 40 additions & 17 deletions apps/frontend/app/components/media.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { useInViewport } from "@mantine/hooks";
import {
EntityLot,
MediaLot,
PersonDetailsDocument,
SeenState,
UserMetadataGroupDetailsDocument,
Expand All @@ -30,7 +31,7 @@ import {
IconStarFilled,
} from "@tabler/icons-react";
import { useQuery } from "@tanstack/react-query";
import type { ReactNode } from "react";
import { useMemo, type ReactNode } from "react";
import { Form, Link } from "react-router";
import { $path } from "safe-routes";
import { match } from "ts-pattern";
Expand Down Expand Up @@ -140,7 +141,7 @@ export const MetadataDisplayItem = (props: {
noLeftLabel?: boolean;
}) => {
const [_r, setEntityToReview] = useReviewEntity();
const [_, setMetadataToUpdate, isMetadataToUpdateLoading] =
const [_m, setMetadataToUpdate, isMetadataToUpdateLoading] =
useMetadataProgressUpdate();
const userPreferences = useUserPreferences();
const { ref, inViewport } = useInViewport();
Expand All @@ -150,13 +151,46 @@ export const MetadataDisplayItem = (props: {
props.metadataId,
inViewport,
);

const averageRating = userMetadataDetails?.averageRating;
const completedHistory = (userMetadataDetails?.history || []).filter(
(h) => h.state === SeenState.Completed,
);
const currentProgress = userMetadataDetails?.history.find(
(h) => h.state === SeenState.InProgress,
)?.progress;
const reasons = userMetadataDetails?.mediaReason?.filter((r) =>
[
UserToMediaReason.Finished,
UserToMediaReason.Watchlist,
UserToMediaReason.Owned,
].includes(r),
);
const hasInteracted = userMetadataDetails?.hasInteracted;

const leftLabel = useMemo(() => {
if (props.noLeftLabel || !metadataDetails || !userMetadataDetails)
return null;

const inProgress = userMetadataDetails.inProgress;
if (inProgress) {
if (inProgress.podcastExtraInformation)
return `EP-${inProgress.podcastExtraInformation.episode}`;
if (inProgress.showExtraInformation)
return `S${inProgress.showExtraInformation.season}-E${inProgress.showExtraInformation.episode}`;
}

const nextEntry = userMetadataDetails.nextEntry;
if (nextEntry) {
if (metadataDetails.lot === MediaLot.Show)
return `S${nextEntry.season}-E${nextEntry.episode}`;
if (metadataDetails.lot === MediaLot.Podcast)
return `EP-${nextEntry.episode}`;
}

return metadataDetails.publishYear;
}, [metadataDetails, userMetadataDetails]);

const surroundReason = (
idx: number,
data: readonly [UserToMediaReason, ReactNode],
Expand All @@ -167,14 +201,6 @@ export const MetadataDisplayItem = (props: {
</ThemeIcon>
</Tooltip>
);
const reasons = userMetadataDetails?.mediaReason?.filter((r) =>
[
UserToMediaReason.Finished,
UserToMediaReason.Watchlist,
UserToMediaReason.Owned,
].includes(r),
);
const hasInteracted = userMetadataDetails?.hasInteracted;

return (
<BaseMediaDisplayItem
Expand All @@ -184,15 +210,12 @@ export const MetadataDisplayItem = (props: {
isLoading={isMetadataDetailsLoading}
name={props.name ?? metadataDetails?.title}
imageUrl={metadataDetails?.assets.images.at(0)}
highlightImage={userMetadataDetails?.recentlyConsumed}
highlightImage={userMetadataDetails?.isRecentlyConsumed}
onImageClickBehavior={$path("/media/item/:id", { id: props.metadataId })}
labels={
metadataDetails
? {
left:
props.noLeftLabel !== true
? metadataDetails.publishYear
: undefined,
left: leftLabel,
right:
props.rightLabel ||
(props.rightLabelLot
Expand Down Expand Up @@ -319,7 +342,7 @@ export const MetadataGroupDisplayItem = (props: {
isLoading={isMetadataDetailsLoading}
name={metadataDetails?.details.title}
imageOverlay={{ topRight: props.topRight }}
highlightImage={userMetadataGroupDetails?.recentlyConsumed}
highlightImage={userMetadataGroupDetails?.isRecentlyConsumed}
onImageClickBehavior={$path("/media/groups/item/:id", {
id: props.metadataGroupId,
})}
Expand Down Expand Up @@ -372,7 +395,7 @@ export const PersonDisplayItem = (props: {
name={personDetails?.details.name}
isLoading={isPersonDetailsLoading}
imageOverlay={{ topRight: props.topRight }}
highlightImage={userPersonDetails?.recentlyConsumed}
highlightImage={userPersonDetails?.isRecentlyConsumed}
imageUrl={personDetails?.details.displayImages.at(0)}
onImageClickBehavior={$path("/media/people/item/:id", {
id: props.personId,
Expand Down
1 change: 1 addition & 0 deletions apps/frontend/app/routes/_dashboard.calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const CalendarEvent = (props: {
<ApplicationGrid>
{props.data.events.map((calEvent) => (
<MetadataDisplayItem
noLeftLabel
key={calEvent.calendarEventId}
altName={calEvent.metadataText}
metadataId={calEvent.metadataId}
Expand Down
2 changes: 1 addition & 1 deletion apps/frontend/app/routes/api.auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const loader = async ({ request }: Route.LoaderArgs) => {
GetOidcTokenDocument,
input,
);
console.log("OIDC token response:", getOidcToken);
console.log("OIDC token response:", { getOidcToken });
const oidcInput = {
email: getOidcToken.email,
issuerId: getOidcToken.subject,
Expand Down
4 changes: 2 additions & 2 deletions apps/website/app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { writeFileSync } from "node:fs";
import { PassThrough } from "node:stream";
import { createReadableStreamFromReadable } from "@react-router/node";
import { migrate } from "drizzle-orm/postgres-js/migrator";
Expand All @@ -8,8 +9,7 @@ import {
type EntryContext,
ServerRouter,
} from "react-router";
import { db, serverVariables, TEMP_DIRECTORY } from "./lib/config.server";
import { writeFileSync } from "node:fs";
import { TEMP_DIRECTORY, db, serverVariables } from "./lib/config.server";

migrate(db, { migrationsFolder: "app/drizzle/migrations" }).catch((error) => {
console.error("Database migrations failed", error);
Expand Down
4 changes: 2 additions & 2 deletions apps/website/app/lib/config.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,15 @@ export const sendEmail = async (
});
const html = await render(element, { pretty: true });
const text = await render(element, { plainText: true });
console.log(`Sending email to ${recipient} with subject ${subject}`);
console.log("Sending email:", { recipient, subject });
const resp = await client.sendMail({
text,
html,
subject,
to: recipient,
from: serverVariables.SERVER_SMTP_MAILBOX,
});
console.log(`Sent email to ${recipient} with subject ${subject}`);
console.log("Sent email:", { recipient, subject });
return resp.messageId;
};

Expand Down
3 changes: 2 additions & 1 deletion apps/website/app/routes/_index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const action = async ({ request }: Route.ActionArgs) => {
const { email } = processSubmission(formData, emailSchema);
const otpCode = generateOtp(6);
otpCodesCache.set(email, otpCode);
console.log(`OTP code for ${email} is ${otpCode}`);
console.log("OTP code generated:", { email, otpCode });
await sendEmail(
email,
LoginCodeEmail.subject,
Expand All @@ -111,6 +111,7 @@ export const action = async ({ request }: Route.ActionArgs) => {
const customerId = dbCustomer.at(0)?.id;
if (!customerId)
throw new Error("There was an error registering the user.");
console.log("Customer login successful:", { customerId });
return redirect($path("/me"), {
headers: {
"set-cookie": await websiteAuthCookie.serialize(customerId),
Expand Down
1 change: 1 addition & 0 deletions apps/website/app/routes/callback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const loader = async ({ request }: Route.LoaderArgs) => {
})
.otherwise((value) => value.id);
if (!customerId) throw new Error("There was an error registering the user.");
console.log("Customer login successful:", { customerId });
return redirect($path("/me"), {
headers: { "set-cookie": await websiteAuthCookie.serialize(customerId) },
});
Expand Down
16 changes: 8 additions & 8 deletions apps/website/app/routes/paddle-webhook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,15 @@ export const action = async ({ request }: Route.ActionArgs) => {

const { eventType, data } = eventData;

console.log(`Received event: ${eventType}`);
console.log("Received event:", { eventType });

if (eventType === EventName.TransactionCompleted) {
const paddleCustomerId = data.customerId;
if (!paddleCustomerId)
return Response.json({
error: "No customer ID found in transaction completed event",
});
console.log(
`Received transaction completed event for customer id: ${paddleCustomerId}`,
);
console.log("Received transaction completed event", { paddleCustomerId });
let customer = await db.query.customers.findFirst({
where: eq(customers.paddleCustomerId, paddleCustomerId),
});
Expand All @@ -80,9 +78,11 @@ export const action = async ({ request }: Route.ActionArgs) => {
if (!priceId) return Response.json({ error: "Price ID not found" });

const { planType, productType } = getProductAndPlanTypeByPriceId(priceId);
console.log(
`Customer ${paddleCustomerId} purchased ${productType} with plan type ${planType}`,
);
console.log("Customer purchased plan:", {
paddleCustomerId,
productType,
planType,
});

const { email, oidcIssuerId } = customer;
const renewOn = getRenewOnFromPlanType(planType);
Expand Down Expand Up @@ -148,7 +148,7 @@ export const action = async ({ request }: Route.ActionArgs) => {
} else {
const renewal = getRenewOnFromPlanType(customer.planType);
const renewOn = renewal ? formatDateToNaiveDate(renewal) : undefined;
console.log(`Updating customer with renewOn: ${renewOn}`);
console.log("Updating customer with renewOn", { renewOn });
await db
.update(customers)
.set({ renewOn, hasCancelled: null })
Expand Down
12 changes: 6 additions & 6 deletions crates/models/dependent/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,32 +345,32 @@ pub struct CoreDetails {

#[derive(SimpleObject)]
pub struct UserPersonDetails {
pub recently_consumed: bool,
pub reviews: Vec<ReviewItem>,
pub is_recently_consumed: bool,
pub collections: Vec<collection::Model>,
}

#[derive(SimpleObject)]
pub struct UserMetadataGroupDetails {
pub recently_consumed: bool,
pub reviews: Vec<ReviewItem>,
pub is_recently_consumed: bool,
pub collections: Vec<collection::Model>,
}

#[derive(SimpleObject)]
pub struct UserMetadataDetails {
/// Whether this media has been interacted with
pub has_interacted: bool,
/// Whether this media has been recently interacted with
pub recently_consumed: bool,
/// The public reviews of this media.
pub reviews: Vec<ReviewItem>,
/// The number of users who have seen this media.
pub seen_by_all_count: usize,
/// The number of times this user has seen this media.
pub seen_by_user_count: usize,
/// The seen history of this media.
pub history: Vec<seen::Model>,
/// The number of times this user has seen this media.
pub seen_by_user_count: usize,
/// Whether this media has been recently interacted with
pub is_recently_consumed: bool,
/// The average rating of this media in this service.
pub average_rating: Option<Decimal>,
/// The seen item if it is in progress.
Expand Down
12 changes: 6 additions & 6 deletions crates/services/miscellaneous/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ ORDER BY RANDOM() LIMIT 10;
} else {
None
};
let recently_consumed =
let is_recently_consumed =
get_entity_recently_consumed(&user_id, &metadata_id, EntityLot::Metadata, &self.0)
.await?;
Ok(UserMetadataDetails {
Expand All @@ -634,8 +634,8 @@ ORDER BY RANDOM() LIMIT 10;
show_progress,
average_rating,
podcast_progress,
recently_consumed,
seen_by_user_count,
is_recently_consumed,
seen_by_all_count: seen_by,
has_interacted: user_to_meta.is_some(),
media_reason: user_to_meta.and_then(|n| n.media_reason),
Expand All @@ -650,12 +650,12 @@ ORDER BY RANDOM() LIMIT 10;
let reviews = item_reviews(&user_id, &person_id, EntityLot::Person, true, &self.0).await?;
let collections =
entity_in_collections(&self.0.db, &user_id, &person_id, EntityLot::Person).await?;
let recently_consumed =
let is_recently_consumed =
get_entity_recently_consumed(&user_id, &person_id, EntityLot::Person, &self.0).await?;
Ok(UserPersonDetails {
reviews,
collections,
recently_consumed,
is_recently_consumed,
})
}

Expand All @@ -679,7 +679,7 @@ ORDER BY RANDOM() LIMIT 10;
&self.0,
)
.await?;
let recently_consumed = get_entity_recently_consumed(
let is_recently_consumed = get_entity_recently_consumed(
&user_id,
&metadata_group_id,
EntityLot::MetadataGroup,
Expand All @@ -689,7 +689,7 @@ ORDER BY RANDOM() LIMIT 10;
Ok(UserMetadataGroupDetails {
reviews,
collections,
recently_consumed,
is_recently_consumed,
})
}

Expand Down
Loading

0 comments on commit b15244d

Please sign in to comment.